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

tx_extra limitation fix [release-v0.18] #8806

Closed

Conversation

SChernykh
Copy link
Contributor

@SChernykh SChernykh commented Mar 27, 2023

  • Fixed connection drop when a big tx_extra is received from another node
  • Double check for MAX_TX_EXTRA_SIZE before sending out ZMQ txpool_event notifications to properly mark them as invalid

The second fix (ZMQ notifications) is to stop the notification spam when a new block with big tx_extra transactions is received - it brings unneccessary load to p2pool miners.


if(tvc[i].m_verifivation_failed)
{MERROR_VER("Transaction verification failed: " << results[i].hash);}
else if(tvc[i].m_verifivation_impossible)
{MERROR_VER("Transaction verification impossible: " << results[i].hash);}

if(tvc[i].m_added_to_pool)
if(tvc[i].m_added_to_pool && (results[i].tx.extra.size() <= MAX_TX_EXTRA_SIZE))
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this check necessary? m_added_to_pool is only ever set after the tx.extra checks in add_new_tx. In other words, it seems redundant because m_added_to_pool will be false if tx.extra is too big anyways.

Copy link
Contributor Author

@SChernykh SChernykh Mar 27, 2023

Choose a reason for hiding this comment

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

It can happen if kept_by_block is true, and then I get tx spam in p2pool logs - all big tx_extra transactions get added to a new block and leak into ZMQ notifications, but they shouldn't because ZMQ notifications are supposed to notify about mempool only.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jeffro256 I just did a quick test by adding some logging: https://paste.debian.net/hidden/15de343a/
I can see both places filtering transactions from being sent to ZMQ subscribers, so it's correct. tvc[i].m_added_to_pool can be true but we still end up in the else branch, and the debug logging shows it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correction: https://paste.debian.net/hidden/d345d788/ - now I see only the first place filtering transactions, I'll keep running it to see if the second one triggers or not.

Copy link
Contributor

Choose a reason for hiding this comment

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

if(tvc[i].m_added_to_pool...
but they shouldn't because ZMQ notifications are supposed to notify about mempool only.

These two things seem to be contradicting each other ^. Is there a deeper problem here with the meaning of m_added_to_pool?

Copy link
Contributor Author

@SChernykh SChernykh Mar 27, 2023

Choose a reason for hiding this comment

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

When a new block arrives, monerod downloads missing transactions from this block, adds them to mempool for a split second and then removes them from mempool and adds them to the blockchain. All this juggling triggers ZMQ notifications which are useless to subscribers. So m_added_to_pool is technically correct here, but useless in practice.

Copy link
Contributor

Choose a reason for hiding this comment

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

Since downloaded transactions are "forced into" the mempool by kept_by_block, can we not generalize this condition to tvc[i].m_added_to_pool && tx_relay != relay_method::block? This would exclude any internal blockchain shufflings inside the pool, not just for tx_extra.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll run with debug logging to confirm that it's only relay_method::block there, and if it is, I'll change to && tx_relay != relay_method::block

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jeffro256 I just realized that kept_by_block can make transactions stay in mempool for real, and be actually valid to be mined again, for example after a reorg. So it's a bad idea to change to tx_relay != relay_method::block, it's better to filter only big tx_extra.

@UkoeHB
Copy link
Contributor

UkoeHB commented Mar 27, 2023

Follow up PR: it looks like this same problem can occur for txs with too-low fees (a bit surprising it has never been encountered - a testament to the fee algorithm's adoption perhaps). Minimum fee is a relay-only rule like the tx extra cap.

drop_connection(context, false, false);
// Don't drop connections which send transactions with too big tx_extra
// It will only cause updated nodes to isolate themselves from the rest of the network
// This check can be removed as soon as updated nodes are the majority (both by hashrate and by total count)
Copy link
Contributor

Choose a reason for hiding this comment

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

// This check can be removed as soon as updated nodes are the majority (both by hashrate and by total count)

It's not clear to me this is the best strategy/philosophy for managing the network (i.e. blacklisting nodes that don't align with your node's relay rules), you may want to bring it up in -dev.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"can be removed" != "must be removed", not even "should be removed"

Copy link
Contributor

Choose a reason for hiding this comment

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

"can be removed" = it's fine to remove it, but I am saying that's not necessarily true.


if(tvc[i].m_verifivation_failed)
{MERROR_VER("Transaction verification failed: " << results[i].hash);}
else if(tvc[i].m_verifivation_impossible)
{MERROR_VER("Transaction verification impossible: " << results[i].hash);}

if(tvc[i].m_added_to_pool)
if(tvc[i].m_added_to_pool && (results[i].tx.extra.size() <= MAX_TX_EXTRA_SIZE))
Copy link
Contributor

Choose a reason for hiding this comment

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

if(tvc[i].m_added_to_pool...
but they shouldn't because ZMQ notifications are supposed to notify about mempool only.

These two things seem to be contradicting each other ^. Is there a deeper problem here with the meaning of m_added_to_pool?

- Fixed connection drop when a big tx_extra is received from another node
- Double check for MAX_TX_EXTRA_SIZE before sending out ZMQ txpool_event notifications to properly mark them as `invalid`
Copy link

@thereeroyz thereeroyz left a comment

Choose a reason for hiding this comment

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

src/cryptonote_protocol/cryptonote_protocol_handler.inc olabilir mi ?

@SChernykh SChernykh changed the title tx_extra limitation fix tx_extra limitation fix [release-v0.18] Mar 29, 2023
@SChernykh
Copy link
Contributor Author

Replaced with #8813

@SChernykh SChernykh closed this Mar 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants