BitLab 0.1.0
BitLab: A Browser for the Bitcoin P2P Network and Blockchain
|
#include "peer_connection.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <time.h>
#include <errno.h>
#include <stdint.h>
#include <openssl/sha.h>
#include <pthread.h>
#include <sys/time.h>
#include <stdbool.h>
#include <bits/pthreadtypes.h>
#include "peer_queue.h"
#include "utils.h"
#include "log.h"
#include "ip.h"
Go to the source code of this file.
Functions | |
void | parse_inv_message (const unsigned char *payload, size_t payload_len) |
void | handle_inv_message (int idx, const unsigned char *payload, size_t payload_len) |
size_t | build_getblocks_message (unsigned char *buffer, size_t buffer_size, const unsigned char *block_locator, size_t locator_count) |
size_t | write_var_int (unsigned char *buf, uint64_t value) |
void | decode_transactions (const unsigned char *block_data, size_t block_len) |
static void | compute_checksum (const unsigned char *payload, size_t payload_len, unsigned char out[4]) |
compute_checksum: Calculate the double-SHA256 of the payload, then copy the first 4 bytes into out[4] as the checksum. | |
static size_t | build_version_payload (unsigned char *buf, size_t buf_size) |
build_version_payload: Build a minimal "version" message payload. | |
static size_t | build_message (unsigned char *buf, size_t buf_size, const char *command, const unsigned char *payload, size_t payload_len) |
build_message: Creates a Bitcoin P2P message (header + payload) in buf . | |
size_t | build_getheaders_message (unsigned char *buffer, size_t buffer_size, const unsigned char *block_locator, size_t locator_count) |
void | compute_block_hash (const unsigned char *block_header, unsigned char *output_hash) |
void | list_connected_nodes () |
Lists all connected nodes and their details. | |
int | get_idx (const char *ip_address) |
Get the index of the node with the given IP address. | |
void | send_getaddr_and_wait (int idx) |
Sends a 'getaddr' message to the peer and waits for a response. | |
ssize_t | send_addr (int sockfd, const char *ip_addr) |
send_addr: Sends the 'addr' message to the specified socket with the list of peers. | |
static ssize_t | send_verack (int sockfd, const char *ip_addr) |
send_verack: Constructs a verack message with an empty payload (length = 0) and a valid 4-byte checksum for an empty payload. | |
static ssize_t | send_pong (int sockfd, const unsigned char *nonce8) |
send_pong: Send a "pong" message echoing the same 8-byte nonce from a "ping" payload. | |
ssize_t | send_ping (int sockfd, const char *ip_addr) |
void | initialize_node (Node *node, const char *ip, uint16_t port, int socket_fd) |
void * | peer_communication (void *arg) |
void | create_peer_thread (Node *node) |
int | connect_to_peer (const char *ip_addr) |
Connects to a peer using the specified IP address. | |
void | disconnect (int node_id) |
Disconnects from the node specified by the node ID. | |
void | print_block_header (const unsigned char *header) |
void | parse_headers_message (const unsigned char *payload, size_t payload_len) |
void | load_latest_known_block_hash (unsigned char *block_hash) |
void | send_getheaders_and_wait (int idx) |
Sends a 'getheaders' message to the peer and waits for a response. | |
void | send_headers (int idx, const unsigned char *start_hash, const unsigned char *stop_hash) |
Sends a 'headers' message to the peer. | |
void | save_blocks_to_file (const unsigned char *payload, size_t payload_len, const char *filename) |
unsigned char * | load_blocks_from_file (const char *filename, size_t *payload_len) |
void | send_getblocks_and_wait (int idx) |
Sends a 'getblocks' message to the peer and waits for a response. | |
size_t | build_getdata_message (unsigned char *buffer, size_t buffer_size, const unsigned char *hashes, size_t hash_count) |
void | send_getdata_and_wait (int idx, const unsigned char *hashes, size_t hash_count) |
Sends a 'getdata' message to the peer and waits for a response. | |
size_t | build_inv_message (unsigned char *buffer, size_t buffer_size, const unsigned char *inv_data, size_t inv_count) |
Builds an 'inv' message. | |
void | send_inv_and_wait (int idx, const unsigned char *inv_data, size_t inv_count) |
Sends an 'inv' message to the peer. | |
void | send_tx (int idx, const unsigned char *tx_data, size_t tx_size) |
Sends a 'tx' message to the specified node. | |
Variables | |
Node | nodes [MAX_NODES] |
size_t build_getblocks_message | ( | unsigned char * | buffer, |
size_t | buffer_size, | ||
const unsigned char * | block_locator, | ||
size_t | locator_count | ||
) |
Definition at line 1594 of file peer_connection.c.
References build_message(), and write_var_int().
Referenced by send_getblocks_and_wait().
size_t build_getdata_message | ( | unsigned char * | buffer, |
size_t | buffer_size, | ||
const unsigned char * | hashes, | ||
size_t | hash_count | ||
) |
Definition at line 1699 of file peer_connection.c.
References build_message(), and write_var_int().
Referenced by send_getdata_and_wait().
size_t build_getheaders_message | ( | unsigned char * | buffer, |
size_t | buffer_size, | ||
const unsigned char * | block_locator, | ||
size_t | locator_count | ||
) |
Definition at line 178 of file peer_connection.c.
References build_message(), and write_var_int().
Referenced by send_getheaders_and_wait().
size_t build_inv_message | ( | unsigned char * | buffer, |
size_t | buffer_size, | ||
const unsigned char * | inv_data, | ||
size_t | inv_count | ||
) |
Builds an 'inv' message.
This function builds an 'inv' message with the given inventory data.
buffer | The buffer to store the built message. |
buffer_size | The size of the buffer. |
inv_data | An array of inventory vectors (type + hash). |
inv_count | The number of inventory vectors in the array. |
Definition at line 1814 of file peer_connection.c.
References BITLAB_LOG, build_message(), LOG_DEBUG, log_message(), and write_var_int().
Referenced by send_inv_and_wait().
|
static |
build_message: Creates a Bitcoin P2P message (header + payload) in buf
.
The 'command' is zero-padded to 12 bytes. The payload is appended. We compute the 4-byte double-SHA256 checksum.
Definition at line 135 of file peer_connection.c.
References BITCOIN_MAINNET_MAGIC, bitcoin_msg_header::checksum, bitcoin_msg_header::command, compute_checksum(), bitcoin_msg_header::length, and bitcoin_msg_header::magic.
Referenced by build_getblocks_message(), build_getdata_message(), build_getheaders_message(), build_inv_message(), connect_to_peer(), send_addr(), send_getaddr_and_wait(), send_ping(), and send_pong().
|
static |
build_version_payload: Build a minimal "version" message payload.
This includes: protocol version, services, timestamp, addr_recv, addr_from, nonce, user agent, start_height, and relay.
Definition at line 60 of file peer_connection.c.
References BITCOIN_MAINNET_PORT.
Referenced by connect_to_peer().
void compute_block_hash | ( | const unsigned char * | block_header, |
unsigned char * | output_hash | ||
) |
Definition at line 209 of file peer_connection.c.
|
static |
compute_checksum: Calculate the double-SHA256 of the payload, then copy the first 4 bytes into out[4]
as the checksum.
Definition at line 39 of file peer_connection.c.
Referenced by build_message(), send_headers(), send_tx(), and send_verack().
int connect_to_peer | ( | const char * | ip_addr | ) |
Connects to a peer using the specified IP address.
This function attempts to establish a connection to a peer using the given IP address. It returns a socket file descriptor if the connection is successful, or -1 if it fails.
ip_addr | The IP address of the peer to connect to. |
Definition at line 1032 of file peer_connection.c.
References BITCOIN_MAINNET_MAGIC, BITCOIN_MAINNET_PORT, build_message(), build_version_payload(), bitcoin_msg_header::command, create_peer_thread(), guarded_print_line(), init_logging(), initialize_node(), bitcoin_msg_header::length, log_message(), LOG_WARN, bitcoin_msg_header::magic, MAX_NODES, nodes, and send_verack().
Referenced by cli_connect().
void create_peer_thread | ( | Node * | node | ) |
Definition at line 1017 of file peer_connection.c.
References peer_communication(), and Node::thread.
Referenced by connect_to_peer().
void decode_transactions | ( | const unsigned char * | block_data, |
size_t | block_len | ||
) |
Definition at line 1977 of file peer_connection.c.
References read_var_int().
Referenced by send_getdata_and_wait().
void disconnect | ( | int | node_id | ) |
Disconnects from the node specified by the node ID.
This function disconnects from the node specified by the given node ID. It closes the socket, terminates the thread, and logs the disconnection.
node_id | The ID of the node in the nodes array to disconnect from. |
Definition at line 1236 of file peer_connection.c.
References Node::ip_address, Node::is_connected, LOG_INFO, log_message(), MAX_NODES, nodes, Node::port, Node::socket_fd, and Node::thread.
Referenced by cli_disconnect().
int get_idx | ( | const char * | ip_address | ) |
Get the index of the node with the given IP address.
ip_address | The IP address of the node. |
Definition at line 291 of file peer_connection.c.
References MAX_NODES, and nodes.
Referenced by peer_communication().
void handle_inv_message | ( | int | idx, |
const unsigned char * | payload, | ||
size_t | payload_len | ||
) |
Definition at line 1657 of file peer_connection.c.
References BITLAB_LOG, log_message(), LOG_WARN, read_var_int(), and send_getdata_and_wait().
Referenced by peer_communication(), and send_inv_and_wait().
void initialize_node | ( | Node * | node, |
const char * | ip, | ||
uint16_t | port, | ||
int | socket_fd | ||
) |
Definition at line 734 of file peer_connection.c.
References Node::ip_address, Node::is_connected, Node::port, and Node::socket_fd.
Referenced by connect_to_peer().
void list_connected_nodes | ( | ) |
Lists all connected nodes and their details.
This function iterates through the list of nodes and prints the details of each node that is currently connected.
Definition at line 269 of file peer_connection.c.
References guarded_print_line(), MAX_NODES, and nodes.
Referenced by cli_list().
unsigned char * load_blocks_from_file | ( | const char * | filename, |
size_t * | payload_len | ||
) |
Definition at line 1491 of file peer_connection.c.
References guarded_print().
Referenced by cli_inv(), and peer_communication().
void load_latest_known_block_hash | ( | unsigned char * | block_hash | ) |
Definition at line 1315 of file peer_connection.c.
References HEADERS_FILE.
Referenced by send_getblocks_and_wait(), and send_getheaders_and_wait().
void parse_headers_message | ( | const unsigned char * | payload, |
size_t | payload_len | ||
) |
Definition at line 1295 of file peer_connection.c.
References HEADERS_FILE, and print_block_header().
Referenced by send_getheaders_and_wait().
void parse_inv_message | ( | const unsigned char * | payload, |
size_t | payload_len | ||
) |
Definition at line 1625 of file peer_connection.c.
References guarded_print(), and read_var_int().
Referenced by send_getblocks_and_wait().
void * peer_communication | ( | void * | arg | ) |
Definition at line 742 of file peer_connection.c.
References BITCOIN_MAINNET_MAGIC, bitcoin_msg_header::command, Node::compact_blocks, Node::fee_rate, get_idx(), handle_inv_message(), Node::ip_address, Node::is_connected, bitcoin_msg_header::length, load_blocks_from_file(), LOG_ERROR, LOG_INFO, log_message(), LOG_WARN, bitcoin_msg_header::magic, Node::operation_in_progress, send_addr(), send_headers(), send_ping(), send_pong(), and Node::socket_fd.
Referenced by create_peer_thread().
void print_block_header | ( | const unsigned char * | header | ) |
Definition at line 1266 of file peer_connection.c.
Referenced by parse_headers_message().
void save_blocks_to_file | ( | const unsigned char * | payload, |
size_t | payload_len, | ||
const char * | filename | ||
) |
Definition at line 1477 of file peer_connection.c.
References guarded_print().
Referenced by send_getblocks_and_wait().
ssize_t send_addr | ( | int | sockfd, |
const char * | ip_addr | ||
) |
send_addr: Sends the 'addr' message to the specified socket with the list of peers.
The addresses are converted to IPv6-mapped IPv4 addresses.
Parameters: sockfd - The socket file descriptor to send the message to. ip_addr - The IP address of the peer to log the message.
Returns: The number of bytes sent on success, or -1 on failure.
Definition at line 541 of file peer_connection.c.
References build_message(), get_peer_queue(), guarded_print_line(), LOG_INFO, and log_message().
Referenced by peer_communication().
void send_getaddr_and_wait | ( | int | idx | ) |
Sends a 'getaddr' message to the peer and waits for a response.
This function sends a 'getaddr' message to the peer identified by the given index and waits for a response. It is used to request a list of known peers from the connected peer.
idx | The index of the peer in the nodes array. |
Definition at line 303 of file peer_connection.c.
References add_peer_to_queue(), BITCOIN_MAINNET_MAGIC, build_message(), bitcoin_msg_header::command, guarded_print_line(), Node::ip_address, Node::is_connected, is_in_private_network(), is_valid_ipv4(), bitcoin_msg_header::length, LOG_INFO, log_message(), LOG_WARN, bitcoin_msg_header::magic, MAX_NODES, nodes, Node::operation_in_progress, read_var_int(), and Node::socket_fd.
Referenced by cli_getaddr().
void send_getblocks_and_wait | ( | int | idx | ) |
Sends a 'getblocks' message to the peer and waits for a response.
This function sends a 'getblocks' message to the peer identified by the given index and waits for a response. It is used to request a list of blocks from the connected peer. The response is processed and the blocks are saved to a file.
idx | The index of the peer in the nodes array. |
Definition at line 1518 of file peer_connection.c.
References build_getblocks_message(), guarded_print(), Node::ip_address, load_latest_known_block_hash(), LOG_INFO, log_message(), MAX_LOCATOR_COUNT, MAX_NODES, nodes, Node::operation_in_progress, parse_inv_message(), save_blocks_to_file(), and Node::socket_fd.
Referenced by cli_getblocks().
void send_getdata_and_wait | ( | int | idx, |
const unsigned char * | hashes, | ||
size_t | hash_count | ||
) |
Sends a 'getdata' message to the peer and waits for a response.
This function sends a 'getdata' message to the peer identified by the given index and waits for a response. It is used to request specific blocks or transactions from the connected peer based on the provided hashes. The response is saved to a file and logged to the Bitlab logs.
idx | The index of the peer in the nodes array. |
hashes | An array of hashes representing the blocks or transactions to request. |
hash_count | The number of hashes in the array. |
Definition at line 1728 of file peer_connection.c.
References BITCOIN_MAINNET_MAGIC, build_getdata_message(), bitcoin_msg_header::command, decode_transactions(), Node::ip_address, bitcoin_msg_header::length, LOG_INFO, log_message(), bitcoin_msg_header::magic, MAX_NODES, nodes, Node::operation_in_progress, and Node::socket_fd.
Referenced by cli_getdata(), and handle_inv_message().
void send_getheaders_and_wait | ( | int | idx | ) |
Sends a 'getheaders' message to the peer and waits for a response.
This function sends a 'getheaders' message to the peer identified by the given index and waits for a response. It is used to request a list of known peers from the connected peer.
idx | The index of the peer in the nodes array. |
Definition at line 1330 of file peer_connection.c.
References build_getheaders_message(), guarded_print(), Node::ip_address, load_latest_known_block_hash(), LOG_INFO, log_message(), MAX_LOCATOR_COUNT, MAX_NODES, nodes, Node::operation_in_progress, parse_headers_message(), and Node::socket_fd.
Referenced by cli_getheaders().
void send_headers | ( | int | idx, |
const unsigned char * | start_hash, | ||
const unsigned char * | stop_hash | ||
) |
Sends a 'headers' message to the peer.
This function sends a 'headers' message to the peer identified by the given index. It retrieves the block headers from the local storage starting from the specified start hash up to the stop hash or the maximum number of headers allowed.
idx | The index of the peer in the nodes array. |
start_hash | The hash of the first block header to send. |
stop_hash | The hash of the last block header to send. |
Definition at line 1395 of file peer_connection.c.
References BITCOIN_MAINNET_MAGIC, compute_checksum(), HEADERS_FILE, htole32, Node::ip_address, LOG_INFO, log_message(), bitcoin_msg_header::magic, MAX_HEADERS_COUNT, MAX_NODES, nodes, and Node::socket_fd.
Referenced by peer_communication().
void send_inv_and_wait | ( | int | idx, |
const unsigned char * | inv_data, | ||
size_t | inv_count | ||
) |
Sends an 'inv' message to the peer.
Sends an 'inv' message to the peer and waits for a response.
This function sends an 'inv' message to the peer identified by the given index. It is used to advertise the knowledge of one or more objects (blocks or transactions). The inventory data is provided as input to the function.
idx | The index of the peer in the nodes array. |
inv_data | An array of inventory vectors (type + hash). |
inv_count | The number of inventory vectors in the array. |
Definition at line 1866 of file peer_connection.c.
References BITCOIN_MAINNET_MAGIC, build_inv_message(), bitcoin_msg_header::command, handle_inv_message(), Node::ip_address, LOG_INFO, log_message(), bitcoin_msg_header::magic, MAX_NODES, nodes, Node::operation_in_progress, Node::socket_fd, and write_var_int().
Referenced by cli_inv().
ssize_t send_ping | ( | int | sockfd, |
const char * | ip_addr | ||
) |
Definition at line 693 of file peer_connection.c.
References build_message(), LOG_INFO, and log_message().
Referenced by peer_communication().
|
static |
send_pong: Send a "pong" message echoing the same 8-byte nonce from a "ping" payload.
Definition at line 669 of file peer_connection.c.
References build_message().
Referenced by peer_communication().
void send_tx | ( | int | idx, |
const unsigned char * | tx_data, | ||
size_t | tx_size | ||
) |
Sends a 'tx' message to the specified node.
This function sends a 'tx' message to the node identified by the given index with the provided transaction data. It constructs the message with the appropriate Bitcoin protocol header and sends it over the network socket associated with the node.
idx | The index of the node in the nodes array. |
tx_data | A pointer to the transaction data in hexadecimal format. |
tx_size | The size of the transaction data in bytes. |
Definition at line 2047 of file peer_connection.c.
References BITCOIN_MAINNET_MAGIC, compute_checksum(), htole32, Node::ip_address, LOG_INFO, log_message(), bitcoin_msg_header::magic, MAX_NODES, nodes, and Node::socket_fd.
Referenced by cli_tx().
|
static |
send_verack: Constructs a verack message with an empty payload (length = 0) and a valid 4-byte checksum for an empty payload.
Definition at line 625 of file peer_connection.c.
References BITCOIN_MAINNET_MAGIC, bitcoin_msg_header::checksum, bitcoin_msg_header::command, compute_checksum(), bitcoin_msg_header::length, LOG_INFO, log_message(), and bitcoin_msg_header::magic.
Referenced by connect_to_peer().
size_t write_var_int | ( | unsigned char * | buf, |
uint64_t | value | ||
) |
Definition at line 216 of file peer_connection.c.
References BITLAB_LOG, LOG_DEBUG, and log_message().
Referenced by build_getblocks_message(), build_getdata_message(), build_getheaders_message(), build_inv_message(), and send_inv_and_wait().
Definition at line 26 of file peer_connection.c.
Referenced by connect_to_peer(), disconnect(), get_idx(), list_connected_nodes(), send_getaddr_and_wait(), send_getblocks_and_wait(), send_getdata_and_wait(), send_getheaders_and_wait(), send_headers(), send_inv_and_wait(), and send_tx().