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

feat!: Address agnostic p2p #5176

Merged

Conversation

dima74
Copy link
Contributor

@dima74 dima74 commented Oct 21, 2024

Context

Fixes #5117

How things currently work:

  • Topology of the peers (public keys and addresses) are stored on-chain.
  • There are (Un)RegisterPeer instructions for changing topology.
  • Initial topology is provided in the genesis block (via RegisterPeer instructions)
  • In case genesis block is not provided to the peer, there is sumeragi.trusted_peers config parameter with addresses of initial peers

Solution

Planned changes:

  • Peer addresses will not be stored on-chain (removed from topology)
  • Each peer will store current peer addresses off-chain and do periodic gossiping
  • Peer A will accept connection from peer B if peer B public key is in topology
  • Peer public address will be added to the config.
    • Public address will be sent when connecting to other peers - so that other peers will know our peer's external address and can broadcast this address to other peers (more details in "Use case: New peer added")
    • Note that peer internal address is already in config - network.address
    • Public port can be different from internal port e.g. in case when peer is in docker or behind nginx

Use case: Peer changes address

  • Initially there are three peers: A, B, C
  • C changes its address
  • C knows addresses of other peers and tries to establish connection with them
  • Other peers accept connection because C public key is in topology

Use case: New peer added

  • Initially there are peers A and B with addresses iroha1:8000 and iroha2:8000
  • We want to add peer C with address iroha3:8000
  • First, we invoke RegisterPeer instruction to add C public key to topology
  • Then peer C is started with the following config:
    • sumeragi.trusted_peers - only peer A
    • network.public_address - iroha3:8000
  • C tries to connect to A
    • A receives connection from 9.9.9.9:52143 (52143 is some random port chosen by C for outcoming connection, and 9.9.9.9 is some IP address, e.g. local IP address in kubernetes cluster)
    • A accepts such connection because C public key is in topology
    • C sends its public address (iroha3:8000) to A
    • A gossip address of C to B
    • B receives address of C and connects to C

Migration Guide

  • New parameter was added (network.public_address in the config, or P2P_PUBLIC_ADDRESS env var). This parameter should contain external address of the peer used for p2p (as seen by other peers)
  • genesis.json — changed topology:

Before:

"topology": [
    {
        "address": "irohad0:1001",
        "id": "ed0120A88F67F9D5D94F63DC57661D0B15054298BBB66B39E601FED71E97CD593A7FDB"
    },
    {
        "address": "irohad0:1002",
        "id": "ed0120647E9781F012EF44281A13D673178767465E1622E7BB1094C4C375B98133DBD1"
    },
    ...
]

After:

"topology": [
    "ed0120A88F67F9D5D94F63DC57661D0B15054298BBB66B39E601FED71E97CD593A7FDB",
    "ed0120647E9781F012EF44281A13D673178767465E1622E7BB1094C4C375B98133DBD1",
    ...
]

Review notes

Most meaningful changes are:

  • crates/iroha_core/src/peers_gossiper.rs - logic related to peers gossiping
  • crates/iroha_p2p/src/network.rs
    • Now peer connects to addresses received from PeersGossiper service. (Previously peer connects to addresses of peers from topology)
    • In each pair of peers, both try to establish initial connection (one of two connections will be dropped based on disambiguator rule). This is needed since when adding new peer, other peers might not know its address
  • crates/iroha_p2p/src/peer.rs - after establishing connection, peer now sends its public_address
  • crates/iroha_data_model/src/peer.rs - moved address from PeerId to Peer

Other changes are mostly related to Peer/PeerId


TODO:

  • Fix tests (in particular multiple_networks)
  • Add new tests
  • Fix docker compose

Checklist

  • I've read CONTRIBUTING.md.
  • (optional) I've written unit tests for the code changes.
  • All review comments have been resolved.
  • All CI checks pass.

@dima74 dima74 self-assigned this Oct 21, 2024
@github-actions github-actions bot added api-changes Changes in the API for client libraries config-changes Changes in configuration and start up of the Iroha labels Oct 21, 2024
Copy link

@BAStos525

@SamHSmith SamHSmith self-assigned this Oct 22, 2024
Copy link
Contributor

@SamHSmith SamHSmith left a comment

Choose a reason for hiding this comment

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

LGTM

crates/iroha_data_model/src/peer.rs Show resolved Hide resolved
crates/iroha_data_model/src/peer.rs Show resolved Hide resolved
crates/iroha_data_model/src/peer.rs Outdated Show resolved Hide resolved
crates/iroha_data_model/src/peer.rs Outdated Show resolved Hide resolved
crates/iroha_data_model/src/peer.rs Outdated Show resolved Hide resolved
crates/iroha_core/src/peers_gossiper.rs Outdated Show resolved Hide resolved
crates/iroha_core/src/peers_gossiper.rs Show resolved Hide resolved
crates/iroha_core/src/peers_gossiper.rs Show resolved Hide resolved
crates/iroha_core/src/peers_gossiper.rs Outdated Show resolved Hide resolved
crates/iroha_core/src/peers_gossiper.rs Outdated Show resolved Hide resolved
crates/iroha_test_network/src/fslock_ports.rs Outdated Show resolved Hide resolved
crates/iroha_test_network/src/lib.rs Outdated Show resolved Hide resolved
crates/iroha_config/src/parameters/user.rs Outdated Show resolved Hide resolved
@0x009922 0x009922 self-assigned this Oct 25, 2024
@dima74 dima74 force-pushed the diralik/address-agnostic-p2p branch 2 times, most recently from 91e7ea6 to 37209a0 Compare October 29, 2024 18:44
@dima74
Copy link
Contributor Author

dima74 commented Oct 29, 2024

Update:

  • Use full public_address (instead of external_port)
  • Store gossip address from each peer independently and use majority rule when choosing address for specific peer
  • Fixed tests

@dima74 dima74 marked this pull request as ready for review October 29, 2024 19:14
@dima74 dima74 requested a review from s8sato as a code owner October 29, 2024 19:14
@dima74 dima74 force-pushed the diralik/address-agnostic-p2p branch from 37209a0 to bcd2b69 Compare October 30, 2024 12:15
Copy link
Contributor

@0x009922 0x009922 left a comment

Choose a reason for hiding this comment

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

LGTM

crates/iroha_test_network/src/lib.rs Outdated Show resolved Hide resolved
Signed-off-by: Dmitry Murzin <[email protected]>
@dima74 dima74 force-pushed the diralik/address-agnostic-p2p branch from bcd2b69 to 1194e61 Compare October 31, 2024 08:53
/// Peers received via gossiping from other peers
/// First-level key corresponds to `SocketAddr`
/// Second-level key - peer from which such `SocketAddr` was received
gossip_peers: BTreeMap<PeerId, BTreeMap<PeerId, SocketAddr>>,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need some eviction policy. This can be done separately

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean to periodically drop entries which were received long time ago?

Currently we have eviction based on topology

Copy link
Contributor

@mversic mversic Oct 31, 2024

Choose a reason for hiding this comment

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

Currently we have eviction based on topology

I see, I think then it's ok. Can a malicious actor overwhelm other peer's gossip handle?

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 a malicious actor overwhelm other peer's gossip handle?

Single malicious actor can't, since we choose address using majority rule

Copy link
Contributor

Choose a reason for hiding this comment

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

I get that, but a single malicious actor could send lots of different false addresses, couldn't 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.

Only last entry is kept in the map.


E.g. consider we have three good peers PeerA, PeerB and PeerC and one malicious PeerD. Let's observe how PeerA will determine address of some PeerX. PeerB and PeerC will send correct address GoodPeerX.com:8000 to PeerA, and PeerD will send Bad1PeerX.com:8000. So gossip_peers for PeerA will look like this:

{
  "PeerX": {
    "PeerB": "GoodPeerX.com:8000",
    "PeerC": "GoodPeerX.com:8000",
    "PeerD": "Bad1PeerX.com:8000"
  }
}

Based on majority rule, PeerA will use GoodPeerX.com:8000 as address for PeerX. Next, consider PeerD again sends another bad address Bad2PeerX.com:8000 to PeerA. Now map will change to:

{
  "PeerX": {
    "PeerB": "GoodPeerX.com:8000",
    "PeerC": "GoodPeerX.com:8000",
    "PeerD": "Bad2PeerX.com:8000"
  }
}

Again using majority rule, GoodPeerX.com:8000 will be selected.

Copy link
Contributor

@mversic mversic left a comment

Choose a reason for hiding this comment

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

really well documented

@0x009922 0x009922 merged commit f5e5d20 into hyperledger-iroha:main Nov 1, 2024
16 checks passed
@dima74 dima74 deleted the diralik/address-agnostic-p2p branch November 8, 2024 06:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-changes Changes in the API for client libraries config-changes Changes in configuration and start up of the Iroha
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Address agnostic p2p
5 participants