Skip to content

P2P: Add gossip of BP peers#1265

Merged
heifner merged 64 commits intomainfrom
GH-1245-gossip-bp-peers
Apr 23, 2025
Merged

P2P: Add gossip of BP peers#1265
heifner merged 64 commits intomainfrom
GH-1245-gossip-bp-peers

Conversation

@heifner
Copy link
Copy Markdown
Contributor

@heifner heifner commented Mar 21, 2025

Adds new gossip_bp_peers_message message to P2P protocol for gossip of available "BP" peers. Normally these peers would be canary relay nodes to the block producer and block finalizer nodeos.

       p2p-producer-peer = defproducera
       signature-provider = EOS6y94JK7Dsg3iJCrnvdbyLPZJvaAhfBSU44eU8jkPd4VHX9CJzp=KEY:5J6Z64Jqexample
       p2p-auto-bp-peer = p2p.peer.com:9876

The p2p-producer-peer matches the producer-name of the BP. The key provided to signature-provider is the public/private key of the on-chain key specified with regpeerkey. The p2p-auto-bp-peer is a known BP peer. This is not technically needed if another BP peer has your endpoint listed in their p2p-auto-bp-peer list.

p2p-auto-bp-peer can be specified for as many known bp peers. These will be used along with gossip peers as producers rotate into the producer schedule. They are not gossiped out to other peers. Only this nodes connection info along with other received gossip BP info is gossiped to other peers.

Resolves #1245

@heifner heifner added enhancement New feature or request OCI Work exclusive to OCI team labels Mar 21, 2025
@heifner heifner linked an issue Mar 21, 2025 that may be closed by this pull request
@greg7mdp

This comment was marked as outdated.

@heifner

This comment was marked as outdated.

Comment thread plugins/net_plugin/include/eosio/net_plugin/auto_bp_peering.hpp
Base automatically changed from gh_1183 to main March 24, 2025 19:17
Comment thread plugins/net_plugin/include/eosio/net_plugin/auto_bp_peering.hpp Outdated
Comment thread plugins/net_plugin/include/eosio/net_plugin/auto_bp_peering.hpp Outdated
@heifner heifner requested review from greg7mdp and spoonincode April 16, 2025 16:53

void update_peer_keys(fc::time_point deadline) {
void update_peer_keys() {
// if syncing or replaying old blocks don't bother updating peer keys
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

good call I didn't think of this when reviewing other PR

Comment thread libraries/chain/controller.cpp
Comment thread libraries/chain/include/eosio/chain/peer_keys_db.hpp Outdated
Comment thread plugins/net_plugin/include/eosio/net_plugin/auto_bp_peering.hpp Outdated
@spoonincode
Copy link
Copy Markdown
Contributor

I don't think it was changed in this PR but looking through the code I see it creates and verifies canonical signatures. Maybe consider turning that off (passing false) now from the start of this feature

try {
std::optional<peer_info_t> peer_info = cc.get_peer_info(peer.producer_name);
if (peer_info && peer_info->key) {
public_key_type pk(peer.sig, peer.digest());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we want to immediately kick out SIG_WA. We did make the contract disallow PUB_WA.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment thread plugins/net_plugin/include/eosio/net_plugin/auto_bp_peering.hpp
Comment thread plugins/net_plugin/include/eosio/net_plugin/auto_bp_peering.hpp
Comment thread plugins/net_plugin/include/eosio/net_plugin/auto_bp_peering.hpp

fc::lock_guard g(gossip_bps.mtx);
auto& sig_idx = gossip_bps.index.get<by_sig>();
for (auto i = msg.peers.begin(); i != msg.peers.end() && !fatal_error;) {
Copy link
Copy Markdown
Contributor

@greg7mdp greg7mdp Apr 22, 2025

Choose a reason for hiding this comment

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

I don't think we need to exit the loop early if fatal_error is true (it is after all an optimization for a very unlikely case).

And if we don't, we can use std::erase instead of that for loop which makes the code clearer I feel.

But up to you what you prefer!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: Maybe invalid_message would be more descriptive than fatal_error.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it is important to exit early on a bad public_key. Seems like those could be crafted to be expensive to evaluate. As soon as one is determined to be invalid, don't bother trying to verify signature on any others.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

@greg7mdp greg7mdp Apr 22, 2025

Choose a reason for hiding this comment

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

Seems like those could be crafted to be expensive to evaluate.

I don't think it is a very likely attack vector from one of the top-50 producers, but OK.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

If the message is not from one of the top-50 we know about then we will not consider that a valid message and will disconnect.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So this means that the attack with invalid signatures is not very likely, right. Not advocating for a change, but just that these messages are among a trusted group (all trusted to see the IP of all block producers, so if there was a rogue element it could probably do more damage by ddos'ing producers as they are scheduled to produce than by forging public keys that take time to validate).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well anyone could send a crafted gossip_bp_peers_message we have to validate to know it is from a valid producer.

This conversation did make me realize that it was a bit too strict. Just because a peer is no longer in the top producers does not mean we should fatal disconnect from them.

Copy link
Copy Markdown
Contributor

@greg7mdp greg7mdp Apr 23, 2025

Choose a reason for hiding this comment

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

Well anyone could send a crafted gossip_bp_peers_message we have to validate to know it is from a valid producer.

Hum, I wonder if the whole message (the std::vector<bp_peer> + sender's name) should not be signed by the peer sending it. Then the first thing we could do is validate that the signature matches the public key of one of the IPs registered for that producer, so we authenticate that it comes from one of the current top-50 producers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We could certainly do that. Not sure it is worth the extra processing. Open to what others think.

@heifner heifner merged commit 02bc051 into main Apr 23, 2025
36 checks passed
@heifner heifner deleted the GH-1245-gossip-bp-peers branch April 23, 2025 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request OCI Work exclusive to OCI team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add P2P gossip_bp_peer message

4 participants