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

Feat/restart nonce better #9

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
8 changes: 6 additions & 2 deletions sto/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,11 @@ def last(config: BoardCommmadConfiguration, limit):


@cli.command(name="tx-restart-nonce")
@click.option('--reset-pending-tx', required=False, help="Delete's any pending tx", type=bool, default=None)
@click.pass_obj
def restart_nonce(config: BoardCommmadConfiguration):
def restart_nonce(config: BoardCommmadConfiguration, reset_pending_tx):


"""Resets the broadcasting account nonce."""

assert is_ethereum_network(config.network)
Expand All @@ -463,7 +466,8 @@ def restart_nonce(config: BoardCommmadConfiguration):
ethereum_node_url=config.ethereum_node_url,
ethereum_private_key=config.ethereum_private_key,
ethereum_gas_limit=config.ethereum_gas_limit,
ethereum_gas_price=config.ethereum_gas_price)
ethereum_gas_price=config.ethereum_gas_price,
reset_pending_tx=reset_pending_tx)

@cli.command(name="tx-next-nonce")
@click.pass_obj
Expand Down
8 changes: 6 additions & 2 deletions sto/ethereum/nonce.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ def restart_nonce(logger: Logger,
ethereum_private_key: str,
ethereum_gas_limit: str,
ethereum_gas_price: str,
reset_pending_tx: bool,

):

check_good_private_key(ethereum_private_key)

web3 = create_web3(ethereum_node_url)
Expand All @@ -36,8 +39,9 @@ def restart_nonce(logger: Logger,

account = service.get_or_create_broadcast_account()
txs = service.get_last_transactions(limit=1)
if txs.count() > 0:
raise HistoryDeleteNeeded("Cannot reset nonce as the database contains txs for {}. Delete database to restart.".format(service.address))
if txs.count() > 0 and reset_pending_tx = True:
service.delete_pending_broadcasts()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't just blindly delete pending transactions. Transactions are created and broadcasted in a particular order.
It is quite possible that the earlier txs might succeed and the later ones will fail. In such case deleting txs and running the same command will force the creation of old ones that succeeded already. This is redundant and we should avoid it.

We should rather find a way to update nonce of all pending transactions in the order they were created.



# read nonce from the network and record to the database
tx_count = web3.eth.getTransactionCount(service.address)
Expand Down
11 changes: 10 additions & 1 deletion sto/ethereum/txservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,15 @@ def get_next_nonce(self):

def ensure_accounts_in_sync(self):
"""Make sure that our internal nonce and external nonce looks correct."""

broadcast_account = self.get_or_create_broadcast_account()

tx_count = self.web3.eth.getTransactionCount(broadcast_account.address)

if tx_count != broadcast_account.current_nonce:
NetworkAndDatabaseNonceOutOfSync("Nonced out of sync. Network: {}, database: {}. Maybe you have a pending broadcasts propagating?".format(tx_count, broadcast_account.current_nonce))



def allocate_transaction(self,
broadcast_account: _BroadcastAccount,
receiver: Optional[str],
Expand Down Expand Up @@ -319,6 +320,14 @@ def get_pending_broadcasts(self) -> Query:
"""All transactions that need to be broadcasted."""
return self.dbsession.query(self.prepared_tx_model).filter_by(broadcasted_at=None).order_by(self.prepared_tx_model.nonce).join(self.broadcast_account_model).filter_by(network=self.network)



def delete_pending_broadcasts(self) -> Query:
"""All transactions that need to be deleted."""
return self.dbsession.delete(self.prepared_tx_model).filter_by(broadcasted_at=None).order_by(self.prepared_tx_model.nonce).join(self.broadcast_account_model).filter_by(network=self.network)



def get_unmined_txs(self) -> Query:
"""All transactions that do not yet have a block assigned."""
return self.dbsession.query(self.prepared_tx_model).filter(self.prepared_tx_model.txid != None).filter_by(result_block_num=None).join(self.broadcast_account_model).filter_by(network=self.network)
Expand Down