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: ban header sync peer if no headers provided #3297

Merged

Conversation

sdbondi
Copy link
Member

@sdbondi sdbondi commented Sep 5, 2021

Description

Adds ban in header sync if peer has indicated that they have a better chain but is unable to provide headers

Motivation and Context

A peer can advertise a higher chain metadata and then return no
headers. This case is likely malicious. In this PR, this is handled
by banning the peer allowing the node to attempt a sync with another peer.

How Has This Been Tested?

Manually

A peer can advertise a higher chain metadata and then return no
headers. This case is likely mallicious. In this PR, this is handled
by banning the peer allowing the node to attempt a sync with another peer.
@aviator-app aviator-app bot merged commit 570e222 into tari-project:development Sep 6, 2021
@sdbondi sdbondi deleted the core-header-sync-peer-ban branch September 6, 2021 11:18
Copy link
Collaborator

@SWvheerden SWvheerden left a comment

Choose a reason for hiding this comment

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

This does look like it fixes the one bug I found that could break the network: #3277

We need some more changes here.
You added if headers.is_empty() { return err
but line 411 also contains a if headers.is_empty() { which makes that unreachable now.

I am more of the opinion we should change find_chain_split to return the first header you both have, then you can check that that is valid and is the same the peer advertised.
Is there another reason that can happen that a peer can return 0 headers

@sdbondi
Copy link
Member Author

sdbondi commented Sep 6, 2021

You could be right, I did rush this one a bit. We should not be syncing from a peer that has the same height as us. Listening should ensure that, but perhaps we should do a get_chain_metadata RPC call before syncing - I don't think that sending the current shared tip header has any value, they must send a valid header that links to the fork tip in any case.

@SWvheerden
Copy link
Collaborator

SWvheerden commented Sep 6, 2021

Yeah, I checked this, this PR broke header sync. If you are exactly 1000 blocks behind, you ban the peer and don't sync.

You get this if you are 1000 blocks behind:

 [c::bn::header_sync] WARN  Invalid remote peer behaviour: Remote peer 1790934e3b56607a2f1fc281f6 advertised a better chain but did not return headers
[c::bn::header_sync] WARN  Banned sync peer because Peer misbehaviour: Invalid remote peer behaviour: Remote peer 1790934e3b56607a2f1fc281f6 advertised a better chain but did not return headers

@sdbondi
Copy link
Member Author

sdbondi commented Sep 6, 2021

Thats not great - need to bring back tests for this protocol. That seems like a bug on the sending side because the find_chain_split call should return RPC not found rather than returning no headers. the empty header case (below this change) was either indicating that we are ahead of the peer or in sync already, so we should not have used the peer in the first place.

edit:

// in BlockchainDatabase::find_headers_after_hash
                  if count == 0 {
                        return Ok(Some((i, Vec::new())));
                    }

edit2: ^ this is not the issue

sdbondi added a commit to sdbondi/tari that referenced this pull request Sep 6, 2021
aviator-app bot pushed a commit that referenced this pull request Sep 6, 2021
Description
---
This reverts commit 570e222.

Motivation and Context
---
#3297 (comment)

Having thought about it a bit - header sync is designed to be self contained. It does not have the information required to ban a peer that "lied" in listening mode. 

Suggest that we pass through the chain metadata and peer that 'kicked' the base node into sync into header sync so 
that the peer can be banned if it fails to follow through. We should also not prevent mining when in header sync until a
split and better chain have been comfirmed by header sync.

How Has This Been Tested?
---
Existing tests pass
Cifko pushed a commit to Cifko/tari that referenced this pull request Sep 10, 2021
Description
---
Adds ban in header sync if peer has indicated that they have a better chain but is unable to provide headers 

Motivation and Context
---
A peer can advertise a higher chain metadata and then return no
headers. This case is likely malicious. In this PR, this is handled
by banning the peer allowing the node to attempt a sync with another peer.

How Has This Been Tested?
---
Manually
Cifko pushed a commit to Cifko/tari that referenced this pull request Sep 10, 2021
…3297) (tari-project#3306)


Description
---
This reverts commit 570e222.

Motivation and Context
---
tari-project#3297 (comment)

Having thought about it a bit - header sync is designed to be self contained. It does not have the information required to ban a peer that "lied" in listening mode. 

Suggest that we pass through the chain metadata and peer that 'kicked' the base node into sync into header sync so 
that the peer can be banned if it fails to follow through. We should also not prevent mining when in header sync until a
split and better chain have been comfirmed by header sync.

How Has This Been Tested?
---
Existing tests pass
@sdbondi sdbondi restored the core-header-sync-peer-ban branch February 3, 2022 05:28
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.

3 participants