static void init_peers(struct net_child_info *nci) { /* * read network peers */ struct peer_manager *peers; peers = peerman_read(); if (!peers) { fprintf(plog, "net: initializing empty peer list\n"); peers = peerman_seed(setting("no_dns") == NULL ? true : false); if (!peerman_write(peers)) { fprintf(plog, "net: failed to write peer list\n"); exit(1); } } char *addnode = setting("addnode"); if (addnode) peerman_addstr(peers, addnode); peerman_sort(peers); if (debugging) fprintf(plog, "net: have %u/%zu peers\n", bp_hashtab_size(peers->map_addr), clist_length(peers->addrlist)); nci->peers = peers; }
static void shutdown_daemon(struct net_child_info *nci) { LOG_BEGIN; bool rc = peerman_write(nci->peers); fprintf(plog, "net: %s %u/%zu peers\n", rc ? "wrote" : "failed to write", bp_hashtab_size(nci->peers->map_addr), clist_length(nci->peers->addrlist)); if (plog != stdout && plog != stderr) { fclose(plog); plog = NULL; } if (setting("free")) { shutdown_nci(nci); bp_hashtab_unref(orphans); bp_hashtab_unref(settings); blkdb_free(&db); bp_utxo_set_free(&uset); } LOG_END; }
static void nc_conns_open(struct net_child_info *nci) { log_debug("net: open connections (have %zu, want %zu more)", nci->conns->len, NC_MAX_CONN - nci->conns->len); while ((bp_hashtab_size(nci->peers->map_addr) > 0) && (nci->conns->len < NC_MAX_CONN)) { /* delete peer from front of address list. it will be * re-added before writing peer file, if successful */ struct peer *peer = peerman_pop(nci->peers); struct nc_conn *conn = nc_conn_new(peer); conn->nci = nci; peer_free(peer); free(peer); log_debug("net: connecting to %s", conn->addr_str); /* are we already connected to this IP? */ if (nc_conn_ip_active(nci, conn->peer.addr.ip)) { log_info("net: already connected to %s", conn->addr_str); goto err_loop; } /* are we already connected to this network group? */ if (nc_conn_group_active(nci, &conn->peer)) { log_info("net: already grouped to %s", conn->addr_str); goto err_loop; } /* initiate non-blocking connect(2) */ if (!nc_conn_start(conn)) { log_info("net: failed to start connection to %s", conn->addr_str); goto err_loop; } /* add to our list of monitored event sources */ conn->ev = event_new(nci->eb, conn->fd, EV_WRITE, nc_conn_evt_connected, conn); if (!conn->ev) { log_info("net: event_new failed on %s", conn->addr_str); goto err_loop; } struct timeval timeout = { conn->nci->net_conn_timeout, }; if (event_add(conn->ev, &timeout) != 0) { log_info("net: event_add failed on %s", conn->addr_str); goto err_loop; } /* add to our list of active connections */ parr_add(nci->conns, conn); continue; err_loop: nc_conn_kill(conn); } }
static bool blkdb_connect(struct blkdb *db, struct blkinfo *bi, struct blkdb_reorg *reorg_info) { memset(reorg_info, 0, sizeof(*reorg_info)); if (blkdb_lookup(db, &bi->hash)) return false; bool rc = false; BIGNUM cur_work; BN_init(&cur_work); u256_from_compact(&cur_work, bi->hdr.nBits); bool best_chain = false; /* verify genesis block matches first record */ if (bp_hashtab_size(db->blocks) == 0) { if (!bu256_equal(&bi->hdr.sha256, &db->block0)) goto out; /* bi->prev = NULL; */ bi->height = 0; BN_copy(&bi->work, &cur_work); best_chain = true; } /* lookup and verify previous block */ else { struct blkinfo *prev = blkdb_lookup(db, &bi->hdr.hashPrevBlock); if (!prev) goto out; bi->prev = prev; bi->height = prev->height + 1; if (!BN_add(&bi->work, &cur_work, &prev->work)) goto out; if (BN_cmp(&bi->work, &db->best_chain->work) > 0) best_chain = true; } /* add to block map */ bp_hashtab_put(db->blocks, &bi->hash, bi); /* if new best chain found, update pointers */ if (best_chain) { struct blkinfo *old_best = db->best_chain; struct blkinfo *new_best = bi; reorg_info->old_best = old_best; /* likely case: new best chain has greater height */ if (!old_best) { while (new_best) { new_best = new_best->prev; reorg_info->conn++; } } else { while (new_best && (new_best->height > old_best->height)) { new_best = new_best->prev; reorg_info->conn++; } } /* unlikely case: old best chain has greater height */ while (old_best && new_best && (old_best->height > new_best->height)) { old_best = old_best->prev; reorg_info->disconn++; } /* height matches, but we are still walking parallel chains */ while (old_best && new_best && (old_best != new_best)) { new_best = new_best->prev; reorg_info->conn++; old_best = old_best->prev; reorg_info->disconn++; } /* reorg analyzed. update database's best-chain pointer */ db->best_chain = bi; } rc = true; out: BN_clear_free(&cur_work); return rc; }