Skip to content
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

Fix underpriced transaction #2943

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/overview_and_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ Using geth

Run the Ethereum client and let it sync::

geth --fast --rpc --rpcapi eth,net,web3
geth --fast --rpc --rpcapi eth,net,web3,txpool

.. note::
When you want to use a testnet add the ``--testnet`` or ``--rinkeby`` flags or set the network id with ``--networkid`` directly.
Expand Down
55 changes: 48 additions & 7 deletions raiden/network/rpc/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,46 @@
log = structlog.get_logger(__name__) # pylint: disable=invalid-name


def discover_next_available_nonce(
web3: Web3,
address: typing.Address,
client_version: str,
) -> typing.Nonce:
"""Returns the next available nonce for `address`."""

if client_version.startswith('Parity'):
return int(web3.manager.request_blocking(
"parity_nextNonce",
[address],
), 16)

# The nonces of the mempool transactions are considered used, and it's
# assumed these transactions are different from the ones currently pending
# in the client. This is a simplification, otherwise it would be necessary
# to filter the local pending transactions based on the mempool.
pool = web3.txpool.inspect or {}

# pool is roughly:
#
# {'queued': {'account1': {nonce1: ... nonce2: ...}, 'account2': ...}, 'pending': ...}
#
# Pending refers to the current block and if it contains transactions from
# the user, these will be the younger transactions. Because this needs the
# largest nonce, queued is checked first.

queued = pool.get('queued', {}).get(address)
if queued:
return max(queued.keys()) + 1

pending = pool.get('pending', {}).get(address)
if pending:
return max(pending.keys()) + 1

# The first valid nonce is 0, therefore the count is already the next
# available nonce
return web3.eth.getTransactionCount(address, 'latest')


def check_address_has_code(
client: 'JSONRPCClient',
address: typing.Address,
Expand Down Expand Up @@ -135,15 +175,13 @@ class JSONRPCClient:
host: Ethereum node host address.
port: Ethereum node port number.
privkey: Local user private key, used to sign transactions.
nonce_offset: Network's default base nonce number.
"""

def __init__(
self,
web3: Web3,
privkey: bytes,
gas_price_strategy: typing.Callable = rpc_gas_price_strategy,
nonce_offset: int = 0,
block_num_confirmations: int = 0,
):
if privkey is None or len(privkey) != 32:
Expand All @@ -164,23 +202,26 @@ def __init__(
_, eth_node = is_supported_client(version)

address = privatekey_to_address(privkey)
transaction_count = web3.eth.getTransactionCount(to_checksum_address(address), 'pending')
_available_nonce = transaction_count + nonce_offset

available_nonce = discover_next_available_nonce(
web3,
to_checksum_address(address),
version,
)

self.eth_node = eth_node
self.privkey = privkey
self.address = address
self.web3 = web3
self.default_block_num_confirmations = block_num_confirmations

self._available_nonce = _available_nonce
self._available_nonce = available_nonce
self._nonce_lock = Semaphore()
self._nonce_offset = nonce_offset

log.debug(
'JSONRPCClient created',
node=pex(self.address),
available_nonce=_available_nonce,
available_nonce=available_nonce,
client=version,
)

Expand Down
2 changes: 1 addition & 1 deletion raiden/tests/utils/geth.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def geth_to_cmd(
cmd.extend([
'--nodiscover',
'--rpc',
'--rpcapi', 'eth,net,web3,personal',
'--rpcapi', 'eth,net,web3,personal,txpool',
'--rpcaddr', '0.0.0.0',
'--networkid', str(chain_id),
'--verbosity', str(verbosity),
Expand Down
8 changes: 6 additions & 2 deletions raiden/ui/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,10 @@ def smoketest(ctx, debug, local_matrix, **kwargs): # pylint: disable=unused-arg

report_file = mktemp(suffix='.log')
configure_logging({'': 'DEBUG'}, log_file=report_file)
click.secho(
f'Report file: {report_file}',
fg='yellow',
)

def append_report(subject, data):
with open(report_file, 'a', encoding='UTF-8') as handler:
Expand Down Expand Up @@ -578,9 +582,9 @@ def _run_smoketest():
append_report('Ethereum stdout', out)
append_report('Ethereum stderr', err)
if success:
print_step(f'Smoketest successful, report was written to {report_file}')
print_step(f'Smoketest successful')
else:
print_step(f'Smoketest had errors, report was written to {report_file}', error=True)
print_step(f'Smoketest had errors', error=True)
return success

if args['transport'] == 'udp':
Expand Down