Node Dynamic IP - zoobc/zoobc-core GitHub Wiki

Node's Dynamic IP System

A Node ip address can be either set statically, by adding myAddress configuratoin parameter (in config.toml) or be fetched from an external internet service (by default ZooBC uses http://checkip.dyndns.org).

Note: There's no check on opened ports, so node owner must make sure his/her node's address is reachable and peer port opened from internet.

Actual registered nodes' addresses are permanently stored in an unmanaged table, kept in sync by the p2p network. Each time a new registered node address is received, it's added to the db as 'pending'. Then, the first time that the node tries to communicate with that peer, it will ask a cryptographically secure proof of origin (a message that prove the address belongs to that peer and registered node) and if is valid, the address will be updated to 'confirmed'.

db schema

To allow the node to keep track of node addresses, a new table is required.

node_address_info table

field descr
node_id node_id relative to this node address
address peer/node address
port peer rpc port
block_height last blockchain height when broadcasting the address
block_hash hash of block at above height
signature signature of node_id + address + height (signed using node private key)
status address status (unset=0, pending=1, confirmed=2)

constraints

  • node_id: primary key + address + port

business logic

sync node_address_info table

The node requests node address list from peers (part of network discovery process) and broadcast its own when required (for instance when the other peer sends a list that doesn't include node's own address). In this process, the node will repeatedly sync and update its node_address_info table (every few seconds), until the blockchain has been fully downloaded, then it will increase the time interval between node address info table sync is triggered (30 minutes in production) to avoid spamming the network with update requests while making sure every node is up to date. Workflow:

  1. sync from peers (get peers addresses): download address list from currently connected peers and insert new addresses / merge update existing with more recent ones (by comparing message info block's height/hash). During download, check if there are missing node addresses, by matching node_id in node_address_info and node_registry (only check registered nodes) and if so request them to other peers for a number of times, or until all resolved peers have been contacted. Updated and new addresses are added to db with 'pending' state.
  2. sync to peers (node's own address): after download (each node), check if we have received node's own ip address from the peer and if not: a. generate a new nodeAddressInfo message b. broadcast to the peer

update/broadcast own address:

Unless statically set in node's configuration file, the node updates its own address at regular time interval, then:

  1. verify if changed since last time in lookup the node_address_info table
  2. if outdated:
  • sign a new message and broadcast new address to resolved peers. When peer receives a new nodeAddressInfo message, if it doesn't have it, after updating its db, re-broadcast to its resolved peers, guaranteeing the whole network eventually receives it
  • add the message to node_address_info db table, setting state to 'confirmed'

node address confirmation:

When a node tries resolving a peer, first checks if it's a priority peer (a peer whos id matches with a registered node) and if so:

  • check if its address is in 'pending' state: - yes: send a proof of origin request to the peer. if peer responds with a valid signature - yes: confirm the pending address, overriding the previous one if in db - no: check if that node has a confirmed address in db. - yes: send a proof of origin request to the peer. if peer responds with a valid signature - yes: remove pending address and leave previous confirmed one in db - no: fallback to 'regular' peer resolution for priority peers

workflow

app startup

  • When node starts: - start sync node_address_info table thread - update/broadcast own address
  • When a priority peer is resolved: - confirm address if pending

p2p apis

  • SendNodeAddressInfo: send/broadcast single peerAddress (client/server): - when receiving: - insert/update node_address_info: - if nodeID already in node_address_info and if signature is not the same - validate the message (signature against node_registry and height/hash against main_block) - if block height in message > block height in node_address_info - insert/update the node_address_info, with state 'pending' - re-broadcast node_address_info to all peers, but the one that has sent the message
  • GetNodeAddressesInfo: request a list of peerAddress by nodeID/s (client/server): - send request to all peers until we fill the list: every downloaded peer address must be validated against node_registry (signature) and main_block tables (block hash and block height) - save new peerAddress in db, setting state to 'pending'