Пример #1
0
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;
}
Пример #2
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);
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}