-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Resend transactions #11167
Resend transactions #11167
Changes from all commits
d8fa253
d2a6ed1
b2766ef
f0ae12c
6c95af4
3837d27
24fe955
645ca3e
7c3be45
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 |
---|---|---|
|
@@ -140,6 +140,8 @@ def __init__( | |
self.validation_semaphore = None | ||
self.local_node_synced = False | ||
self.LONG_SYNC_THRESHOLD = 200 | ||
self.last_wallet_tx_resend_time: int = 0 | ||
self.wallet_tx_resend_timeout_secs: int = 1800 # Duration in seconds | ||
|
||
async def ensure_keychain_proxy(self) -> KeychainProxy: | ||
if self.keychain_proxy is None: | ||
|
@@ -229,6 +231,8 @@ async def _start( | |
if self.state_changed_callback is not None: | ||
self.wallet_state_manager.set_callback(self.state_changed_callback) | ||
|
||
self.last_wallet_tx_resend_time = int(time.time()) | ||
self.wallet_tx_resend_timeout_secs = self.config.get("tx_resend_timeout_secs", 60 * 60) | ||
self.wallet_state_manager.set_pending_callback(self._pending_tx_handler) | ||
self._shut_down = False | ||
self._process_new_subscriptions_task = asyncio.create_task(self._process_new_subscriptions()) | ||
|
@@ -331,7 +335,14 @@ async def _messages_to_resend(self) -> List[Tuple[Message, Set[bytes32]]]: | |
return [] | ||
messages: List[Tuple[Message, Set[bytes32]]] = [] | ||
|
||
records: List[TransactionRecord] = await self.wallet_state_manager.tx_store.get_not_sent() | ||
current_time = int(time.time()) | ||
retry_accepted_txs = False | ||
if self.last_wallet_tx_resend_time < current_time - self.wallet_tx_resend_timeout_secs: | ||
self.last_wallet_tx_resend_time = current_time | ||
retry_accepted_txs = True | ||
records: List[TransactionRecord] = await self.wallet_state_manager.tx_store.get_not_sent( | ||
include_accepted_txs=retry_accepted_txs | ||
) | ||
|
||
for record in records: | ||
if record.spend_bundle is None: | ||
|
@@ -1046,7 +1057,9 @@ async def new_peak_wallet(self, new_peak: wallet_protocol.NewPeakWallet, peer: W | |
|
||
if peer.peer_node_id in self.synced_peers: | ||
await self.wallet_state_manager.blockchain.set_finished_sync_up_to(new_peak.height) | ||
await self.wallet_state_manager.new_peak(new_peak) | ||
|
||
async with self.wallet_state_manager.lock: | ||
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. can you explain a bit why the lock needs to be held here? |
||
await self.wallet_state_manager.new_peak(new_peak) | ||
|
||
async def wallet_short_sync_backtrack(self, header_block: HeaderBlock, peer: WSChiaConnection) -> int: | ||
assert self.wallet_state_manager is not None | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1212,6 +1212,10 @@ async def new_peak(self, peak: wallet_protocol.NewPeakWallet): | |
for wallet_id, wallet in self.wallets.items(): | ||
if wallet.type() == uint8(WalletType.POOLING_WALLET): | ||
await wallet.new_peak(peak.height) | ||
current_time = int(time.time()) | ||
|
||
if self.wallet_node.last_wallet_tx_resend_time < current_time - self.wallet_node.wallet_tx_resend_timeout_secs: | ||
self.tx_pending_changed() | ||
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 take it this will submit all unconfirmed transactions in the wallet, is that right? As I mentioned above, I think we should be careful to not load the network with unnecessary or redundant transactions, so I think the code should make it clear we're not doing that. 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. Yea, there are classes of errors that should likely never retry because they will never actually succeed. I think that will need to wait for a follow-up PR. I think versions < 1.3 always retried the transactions regardless of error as well 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. No, this will not resend transactions that have been rejected by that specific peer. This is handled elsewhere in the code. I agree this is not clear. Bit tangled in here. 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. This will not load the network with unnecessary transactions though, it's only sending them to the nodes you are connected to. These nodes will just ignore it efficiently if they already have it. |
||
|
||
async def add_interested_puzzle_hashes( | ||
self, puzzle_hashes: List[bytes32], wallet_ids: List[int], in_transaction: bool = False | ||
|
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.
I'm envisioning forgotten transactions accrue in the system over time. And a future where a significant load comes from wallets automatically submitting old transactions that will never make it into a block. Perhaps because their fee is too low, or maybe because they're no longer valid.
Do we stop this resending, and delete transactions if we receive an error from the node we're sending them to?
Do we validate transactions periodically? e.g. that the coins the TX spends are still unspent
(It would be great to cover those cases in tests too)
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.
We do not resend if we get an error from a node, only if we got "pending", and it is not confirmed.
I don't believe we validate on the client side before sending - not a bad idea.
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.
I also think we need to enhance the reporting of which transactions are pending, and maybe add your idea about timing out submitted transactions, but that will have to be in another PR.