So there is an issue with tracing certain blocks/transactions on
Polygon, for example:
```
> '{"method": "trace_transaction","params":["0xb198d93f640343a98f90d93aa2b74b4fc5c64f3a649f1608d2bfd1004f9dee0e"],"id":1,"jsonrpc":"2.0"}'
```
gives the error `first run for txIndex 1 error: insufficient funds for
gas * price + value: address 0x10AD27A96CDBffC90ab3b83bF695911426A69f5E
have 16927727762862809 want 17594166808296934`
The reason is that this transaction is from the author of the block,
which doesn't have enough ETH to pay for the gas fee + tx value if he's
not the block author receiving transactions fees.
The issue is that currently the APIs are using `ethash.NewFaker()`
Engine for running traces, etc. which doesn't know how to get the author
for a specific block (which is consensus dependant); as it was noting in
several TODO comments.
The fix is to pass the Engine to the BaseAPI, which can then be used to
create the right Block Context. I chose to split the current Engine
interface in 2, with Reader and Writer, so that the BaseAPI only
receives the Reader one, which might be safer (even though it's only
used for getting the block Author).
this pr adds CLI flag to allow the rpcdaemon to bind to a TCP port.
this is very useful if one wants to maintain a remote connection with
the rpcdaemon without using websocket. This is useful because a lot of
issues come with the websocket protocol (compression, max size, etc).
TCP socket gets around these things (it is just raw json over tcp
stream)
the rpc package already supports this, it was just a matter of adding
the bind.
try `echo
'{"jsonrpc":"2.0","method":"eth_blockNumber","id":"1","params":[""]}' |
nc localhost 8548` as a basic test
to test. Subscriptions are also working (idk how to send keepalives with
netcat)
the default rpc.(*Client).Dial method does not support TCP. I have not
included that in this PR. The code for such is as follow
```
// DialTCP create a new TCP client that connects to the given endpoint.
//
// The context is used for the initial connection establishment. It does not
// affect subsequent interactions with the client.
func DialTCP(ctx context.Context, endpoint string) (*Client, error) {
parsed, err := url.Parse(endpoint)
if err != nil {
return nil, err
}
ans := make(chan *Client)
errc := make(chan error)
go func() {
client, err := newClient(ctx, func(ctx context.Context) (ServerCodec, error) {
conn, err := net.Dial("tcp", parsed.Host)
if err != nil {
return nil, err
}
return NewCodec(conn), nil
})
if err != nil {
errc <- err
return
}
ans <- client
}()
select {
case err := <-errc:
return nil, err
case a := <-ans:
return a, nil
case <-ctx.Done():
return nil, ctx.Err()
}
}
// DialContext creates a new RPC client, just like Dial.
//
// The context is used to cancel or time out the initial connection establishment. It does
// not affect subsequent interactions with the client.
func DialContext(ctx context.Context, rawurl string) (*Client, error) {
u, err := url.Parse(rawurl)
if err != nil {
return nil, err
}
switch u.Scheme {
case "http", "https":
return DialHTTP(rawurl)
case "ws", "wss":
return DialWebsocket(ctx, rawurl, "")
case "tcp":
return DialTCP(ctx, rawurl)
case "stdio":
return DialStdIO(ctx)
case "":
return DialIPC(ctx, rawurl)
default:
return nil, fmt.Errorf("no known transport for URL scheme %q", u.Scheme)
}
}
```
let me know if you would like me to add this to the PR as well. the TCP
connection can then be established with `rpc.Dial("tcp://host:port")`
Moving the txpool transaction pull into the execution phase and looping
until the gas is used up or the txpool runs dry.
Removed the concept of local vs remote transactions as comments/code
showed this split was no longer in use.
Created a `PreparedTxs` collection to satisfy the use case in the
integration tool when mining is active.
Untested locally as I have no way of mining/validating currently.
Co-authored-by: Alex Sharov <AskAlexSharov@gmail.com>