static int bitcui_init(void) { int res; bitcui_set_status("ui starting.."); btcui->poll = poll_create(); res = bitcui_notify_init(&btcui->eventFd, &btcui->notifyFd); ASSERT(res == 0); fx_init(); ncui_init(); bitcui_log_init(); poll_callback_device(btcui->poll, STDIN_FILENO, 1, 0, 1, ncui_input_cb, NULL); poll_callback_time(btcui->poll, 1 * 1000 * 1000 / 2, TRUE, ncui_time_cb, NULL); return 0; }
void bitcui_stop(void) { bitcui_set_status("Exiting.."); bitcui_req_exit(); if (btcui->inuse == 1) { int res; Log(LGPFX " stopping ui thread.\n"); res = pthread_join(btcui->tid, NULL); ASSERT(res == 0); Log(LGPFX " ui thread stopped: %d\n", res); } ASSERT(btcui->lock); mutex_free(btcui->lock); btcui->lock = NULL; ASSERT(btcui->cv); condvar_free(btcui->cv); memset(btcui, 0, sizeof *btcui); }
static int blockset_open_file(struct blockstore *blockStore, struct blockset *bs) { uint64 offset; mtime_t ts; int res; res = file_open(bs->filename, 0 /* R/O */, 0 /* !unbuf */, &bs->desc); if (res) { return res; } bs->filesize = file_getsize(bs->desc); if (bs->filesize < 0) { return errno; } if (bs->filesize > 0) { char *s = print_size(bs->filesize); char *name = file_getname(bs->filename); Log(LGPFX" reading file %s -- %s -- %llu headers.\n", name, s, bs->filesize / sizeof(btc_block_header)); free(name); free(s); } ts = time_get(); offset = 0; while (offset < bs->filesize) { btc_block_header buf[10000]; size_t numRead; size_t numBytes; int numHeaders; int i; numBytes = MIN(bs->filesize - offset, sizeof buf); res = file_pread(bs->desc, offset, buf, numBytes, &numRead); if (res != 0) { break; } if (btc->stop != 0) { res = 1; NOT_TESTED(); break; } numHeaders = numRead / sizeof(btc_block_header); for (i = 0; i < numHeaders; i++) { struct blockentry *be; uint256 hash; be = blockstore_alloc_entry(buf + i); be->written = 1; hash256_calc(buf + i, sizeof buf[0], &hash); if (!blockstore_validate_chkpt(&hash, blockStore->height + 1)) { return 1; } blockstore_add_entry(blockStore, be, &hash); if (i == numHeaders - 1) { bitcui_set_status("loading headers .. %llu%%", (offset + numBytes) * 100 / bs->filesize); } if (i == numHeaders - 1 || (numBytes < sizeof buf && i > numHeaders - 256)) { bitcui_set_last_block_info(&hash, blockStore->height, be->header.timestamp); } } offset += numRead; } ts = time_get() - ts; char hashStr[80]; char *latStr; uint256_snprintf_reverse(hashStr, sizeof hashStr, &blockStore->best_hash); Log(LGPFX" loaded blocks up to %s\n", hashStr); latStr = print_latency(ts); Log(LGPFX" this took %s\n", latStr); free(latStr); return res; }
int txdb_craft_tx(struct txdb *txdb, const struct btc_tx_desc *tx_desc, btc_msg_tx *tx) { struct buff *buf; char hashStr[80]; uint256 txHash; uint64 change; uint32 numCoins; bool relevant; mtime_t ts; int res; res = 0; relevant = 0; tx->version = 1; txdb_prepare_txout(tx_desc, tx); /* * In order to properly size 'tx->txIn', we need to determine how many coins * we're going to use. Right now, let's just vastly overestimate. */ numCoins = hashtable_getnumentries(txdb->hash_txo); tx->tx_in = safe_calloc(numCoins, sizeof *tx->tx_in); txdb_print_coins(txdb, 1); txdb_select_coins(txdb, tx_desc, tx, &change); /* * Change! XXX: fix me. */ if (change > 0) { const char *btc_change; btc_change = wallet_get_change_addr(btc->wallet); tx->out_count++; txdb_set_txo(tx, tx->out_count - 1, btc_change, change); Warning(LGPFX" change: %llu -- %.8f BTC\n", change, change / ONE_BTC); } txdb_sign_tx_inputs(txdb, tx); /* * Now that the tx is ready, serialize it and check that it's not too big. */ btcmsg_print_tx(tx); buf = buff_alloc(); serialize_tx(buf, tx); if (buff_curlen(buf) > BTC_TX_MAX_SIZE) { Warning(LGPFX" tx too large: %zu\n", buff_curlen(buf)); res = 1; goto exit; } hash256_calc(buff_base(buf), buff_curlen(buf), &txHash); uint256_snprintf_reverse(hashStr, sizeof hashStr, &txHash); Warning(LGPFX" %s (%zu bytes)\n", hashStr, buff_curlen(buf)); Log_Bytes(LGPFX" TX: ", buff_base(buf), buff_curlen(buf)); if (bitc_testing) { Warning("TESTING! Not saving/relaying tx.\n"); goto exit; } ts = time(NULL); res = txdb_remember_tx(txdb, 0 /* save to disk */, ts, buff_base(buf), buff_curlen(buf), &txHash, NULL, &relevant); txdb_save_tx_label(tx_desc, hashStr); txdb_export_tx_info(txdb); res = peergroup_new_tx_broadcast(btc->peerGroup, buf, ts + 2 * 60 * 60, &txHash); if (res) { Warning(LGPFX" failed to transmit tx: %d\n", res); bitcui_set_status("got errors while broadcasting tx"); } exit: buff_free(buf); /* * XXX: We should mark the coins used by this tx as "reserved", so that we * do not attempt to use conflicting coins in subsequent TXs. */ return res; }
static int txdb_remember_tx(struct txdb *txdb, bool alreadySaved, mtime_t ts, const uint8 *buf, size_t len, const uint256 *txHash, const uint256 *blkHash, bool *relevant) { struct tx_entry *txe; char hashStr[80]; int res; ASSERT(txHash); ASSERT(relevant); *relevant = 0; /* * We always store the tx in the memory pool, that way we know quickly * whether we've already seen it. */ res = txdb_add_to_hashtable(txdb, buf, len, txHash, blkHash, ts, &txe); if (res) { NOT_TESTED(); return res; } uint256_snprintf_reverse(hashStr, sizeof hashStr, txHash); txdb_process_tx_entry(txdb, txHash, blkHash, &txe->tx, &txe->relevant); if (txe->relevant == 0) { Warning(LGPFX" tx %s not relevant (%u)\n", hashStr, hashtable_getnumentries(txdb->hash_tx)); return 0; } if (alreadySaved) { return 0; } /* * OK -- this transaction is relevant to our wallet. */ *relevant = 1; Warning(LGPFX" tx %s ok (%u)\n", hashStr, hashtable_getnumentries(txdb->hash_tx)); res = txdb_save_tx(txdb, blkHash, txHash, ts, buf, len); if (res == 0) { txdb->tx_seq++; } txdb_export_tx_info(txdb); if (bitc_state_ready()) { int64 value = txdb_get_tx_credit(&txe->tx) - txdb_get_tx_debit(&txe->tx); bitcui_set_status("New payment %s: %.8f BTC", value > 0 ? "received" : "made", 1.0 * value / ONE_BTC); } return res; }