|
78 | 78 | #define DROP_ON_SYNC_WEDGE_THRESHOLD (30 * 1000000000ull) // nanoseconds
|
79 | 79 | #define LAST_ACTIVITY_STALL_THRESHOLD (2.0f) // seconds
|
80 | 80 | #define DROP_PEERS_ON_SCORE -2
|
| 81 | +#define MAX_FLUFFY_BLOCK_DEPTH (2 * CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE) |
81 | 82 |
|
82 | 83 | namespace cryptonote
|
83 | 84 | {
|
@@ -623,6 +624,43 @@ namespace cryptonote
|
623 | 624 | MLOG_P2P_MESSAGE(context << "Received NOTIFY_NEW_FLUFFY_BLOCK " << new_block_hash << " (height "
|
624 | 625 | << arg.current_blockchain_height << ", " << arg.b.txs.size() << " txes)");
|
625 | 626 |
|
| 627 | + // Get top block |
| 628 | + uint64_t top_block_index; |
| 629 | + crypto::hash top_block_id; |
| 630 | + m_core.get_blockchain_top(top_block_index, top_block_id); |
| 631 | + |
| 632 | + // Find the nominal common ancestor of this block and the main chain |
| 633 | + crypto::hash common_ancestor = new_block.prev_id; |
| 634 | + bool is_common_ancestor_known = false; |
| 635 | + uint64_t ancestor_block_index = 0; |
| 636 | + for (size_t i = 0; i < MAX_FLUFFY_BLOCK_DEPTH; ++i) // bounded loop |
| 637 | + { |
| 638 | + block prev_block; |
| 639 | + bool is_ancestor_alt = false; |
| 640 | + is_common_ancestor_known = m_core.get_block_by_hash(common_ancestor, prev_block, &is_ancestor_alt); |
| 641 | + if (is_common_ancestor_known) |
| 642 | + ancestor_block_index = get_block_height(prev_block); |
| 643 | + if (!is_common_ancestor_known || !is_ancestor_alt) |
| 644 | + break; |
| 645 | + common_ancestor = prev_block.prev_id; |
| 646 | + } |
| 647 | + |
| 648 | + // Ignore the block if its common ancestor is unknown or too old |
| 649 | + if (!is_common_ancestor_known || ancestor_block_index > top_block_index) |
| 650 | + { |
| 651 | + MDEBUG("Incoming fluffy block " << new_block_hash << " is an orphan from our perspective, ignoring..."); |
| 652 | + // don't drop the connection because this node may be 2 blocks ahead of us |
| 653 | + return 1; |
| 654 | + } |
| 655 | + const uint64_t ancestor_depth = top_block_index - ancestor_block_index; |
| 656 | + if (ancestor_depth > MAX_FLUFFY_BLOCK_DEPTH) |
| 657 | + { |
| 658 | + MDEBUG("Incoming fluffy block " << new_block_hash << " breaks off from our main chain at block " |
| 659 | + << common_ancestor << ", which has a depth of " << ancestor_depth << ", ignoring..."); |
| 660 | + // don't drop this connection because we may want to sync its deep alternative chain |
| 661 | + return 1; |
| 662 | + } |
| 663 | + |
626 | 664 | // Pause mining and resume after block verification to prevent wasted mining cycles while
|
627 | 665 | // validating the next block. Needs more research into if this is a DoS vector or not. Invalid
|
628 | 666 | // block validation will cause disconnects and bans, so it might not be that bad.
|
|
0 commit comments