Example #1
0
bool blockstore_add_header(struct blockstore *bs, const btc_block_header *hdr,
                           const uint256 *hash, bool *orphan) {
  static unsigned int count;
  struct blockentry *be;

  *orphan = 0;

  /*
   * The caller is supposed to compute the checksum of the header it's adding.
   * Verify that it doesn't get this wrong every few blocks.
   */
  count++;
  if ((count % 32) == 0) {
    uint256 hash0;
    hash256_calc(hdr, sizeof *hdr, &hash0);
    ASSERT(uint256_issame(hash, &hash0));
  }

  be = blockstore_lookup(bs, hash);
  if (be) {
    return 0;
  }

  ASSERT(blockstore_validate_chkpt(hash, bs->height + 1));
  ASSERT(bs->best_chain || uint256_issame(hash, &bs->genesis_hash));

  be = blockstore_alloc_entry(hdr);
  blockstore_add_entry(bs, be, hash);

  *orphan = be->height == -1;

  return 1;
}
Example #2
0
static void
blockstore_add_entry(struct blockstore *bs,
                     struct blockentry *be,
                     const uint256 *hash)
{
   bool s;

   if (bs->best_chain == NULL) {

      s = hashtable_insert(bs->hash_blk, hash, sizeof *hash, be);

      ASSERT(s);
      ASSERT(uint256_issame(hash, &bs->genesis_hash));
      ASSERT(be->prev == NULL);
      ASSERT(bs->height);

      bs->best_chain = be;
      bs->genesis = be;
      bs->height  = 0;
      be->height  = 0;

      memcpy(&bs->best_hash, hash, sizeof *hash);
   } else if (uint256_issame(&be->header.prevBlock, &bs->best_hash)) {

      s = hashtable_insert(bs->hash_blk, hash, sizeof *hash, be);
      ASSERT(s);

      bs->height++;
      be->height = bs->height;

      bs->best_chain->next = be;
      be->prev = bs->best_chain;
      bs->best_chain = be;

      memcpy(&bs->best_hash, hash, sizeof *hash);
   } else {
      char hashStr[80];
      uint32 count;

      be->height = -1;
      count = hashtable_getnumentries(bs->hash_orphans);

      uint256_snprintf_reverse(hashStr, sizeof hashStr, hash);
      Log(LGPFX" block %s orphaned. %u orphan%s total.\n",
          hashStr, count, count > 1 ? "s" : "");

      s = hashtable_insert(bs->hash_orphans, hash, sizeof *hash, be);
      ASSERT(s);

      blockstore_set_best_chain(bs, be, hash);
   }
}
Example #3
0
static bool
blockstore_validate_chkpt(const uint256 *hash,
                          uint32 height)
{
   struct block_cpt_entry *array;
   size_t n;
   int i;

   if (btc->testnet) {
      array = block_cpt_testnet;
      n = ARRAYSIZE(block_cpt_testnet);
   } else {
      array = block_cpt_main;
      n = ARRAYSIZE(block_cpt_main);
   }

   for (i = 0; i < n; i++) {
      if (height == array[i].height) {
         if (!uint256_issame(hash, &array[i].hash)) {
            char str[128];
            uint256_snprintf_reverse(str, sizeof str, hash);
            Warning(LGPFX" chkpt validation failed. height=%u %s\n",
                    height, str);
            return 0;
         }
         return 1;
      }
   }

   return 1;
}
Example #4
0
void bitcui_set_last_block_info(const uint256 *hash, int height,
                                uint32 timestamp) {
  if (ui.inuse == 0) {
    return;
  }

  if (btcui->numBlocks > 0 &&
      uint256_issame(hash, &btcui->blocks[btcui->blockProdIdx].hash)) {
    return;
  }

  mutex_lock(btcui->lock);

  if (btcui->numBlocks < ARRAYSIZE(btcui->blocks)) {
    btcui->numBlocks++;
  }

  btcui->blockProdIdx = (btcui->blockProdIdx + 1) % ARRAYSIZE(btcui->blocks);
  btcui->blocks[btcui->blockProdIdx].hash = *hash;
  btcui->blocks[btcui->blockProdIdx].height = height;
  btcui->blocks[btcui->blockProdIdx].timestamp = timestamp;
  btcui->height = height;

  mutex_unlock(btcui->lock);

  bitcui_req_notify_info_update();
}
Example #5
0
bool
blockstore_is_next(struct blockstore *bs,
                   const uint256 *prev,
                   const uint256 *next)
{
   struct blockentry *be;
   uint256 hash;
   bool s;

   s = hashtable_lookup(bs->hash_blk, prev, sizeof *prev, (void*)&be);
   if (s == 0 || be->next == NULL) {
      return 0;
   }

   hash256_calc(&be->next->header, sizeof be->next->header, &hash);
   return uint256_issame(&hash, next);
}
Example #6
0
File: txdb.c Project: haraldh/bitc
static int
txdb_load_tx(struct txdb *txdb,
             const char  *key,
             size_t       klen,
             const char  *val,
             size_t       vlen)
{
    struct tx_ser_data *txd;
    struct tx_ser_key *txk;
    char hashStr[80];
    bool relevant = 0;
    uint256 txHash;
    bool confirmed;
    int res = 0;

    ASSERT(strncmp(key, "/tx/", 4) == 0);

    txk = txdb_deserialize_tx_key(key, klen);
    txd = txdb_deserialize_tx_data(val, vlen);

    ASSERT(txdb->tx_seq == txk->seq);
    txdb->tx_seq++;

    confirmed = !uint256_iszero(&txd->blkHash);

    hash256_calc(txd->buf, txd->len, &txHash);
    ASSERT(uint256_issame(&txHash, &txk->txHash));
    uint256_snprintf_reverse(hashStr, sizeof hashStr, &txHash);
    LOG(1, (LGPFX" loading %ctx %s\n", confirmed ? 'c' : 'u', hashStr));

    res = txdb_remember_tx(txdb, 1 /* not on disk, just hashtable */,
                           txd->timestamp, txd->buf, txd->len,
                           &txk->txHash, &txd->blkHash, &relevant);

    /*
     * If the transaction is still unconfirmed, add to relay set.
     */
    if (!confirmed) {
        struct buff buf;
        int numSec;

        numSec = time(NULL) - txd->timestamp;

        if (numSec > 0) {
            int hours = numSec / (60 * 60);
            int min  = (numSec % (60 * 60)) / 60;

            Log(LGPFX" unconfirmed tx %s was sent %d hours %d min ago.\n",
                hashStr, hours, min);
        }

        buff_init(&buf, txd->buf, txd->len);

        Log(LGPFX" adding tx %s to relay-set\n", hashStr);
        peergroup_new_tx_broadcast(btc->peerGroup, &buf,
                                   txd->timestamp + 2 * 60 * 60,
                                   &txHash);
    } else {
        uint256_snprintf_reverse(hashStr, sizeof hashStr, &txd->blkHash);
        Log(LGPFX" tx in block %s\n", hashStr);
    }

    free(txd->buf);
    free(txd);
    free(txk);

    return res;
}
Example #7
0
File: txdb.c Project: haraldh/bitc
void
txdb_confirm_one_tx(struct txdb   *txdb,
                    const uint256 *blkHash,
                    const uint256 *txHash)
{
    leveldb_iterator_t *iter;
    struct tx_entry *txe;
    char bkHashStr[80];
    char txHashStr[80];

    ASSERT(!uint256_iszero(blkHash));
    ASSERT(!uint256_iszero(txHash));

    txe = txdb_get_tx_entry(txdb, txHash);
    if (txe == NULL) {
        return;
    }

    if (txe->relevant == 0) {
        txdb_remove_from_hashtable(txdb, txHash);
        NOT_TESTED();
        return;
    }

    if (!uint256_iszero(&txe->blkHash)) {
        /*
         * It's possible for the ASSERT below to fire if a tx is confirmed in
         * a block that is later orphaned. The tx should then be relayed again
         * until it finds its way in a new block.
         */
        ASSERT(uint256_issame(&txe->blkHash, blkHash));
        return;
    }

    peergroup_stop_broadcast_tx(btc->peerGroup, txHash);
    memcpy(&txe->blkHash, blkHash, sizeof *blkHash);

    uint256_snprintf_reverse(bkHashStr, sizeof bkHashStr, blkHash);
    uint256_snprintf_reverse(txHashStr, sizeof txHashStr, txHash);
    Warning(LGPFX" %s confirmed in %s\n", txHashStr, bkHashStr);

    NOT_TESTED();

    iter = leveldb_create_iterator(txdb->db, txdb->rd_opts);
    leveldb_iter_seek_to_first(iter);

    while (leveldb_iter_valid(iter)) {
        struct tx_ser_key *txkey;
        struct tx_ser_data *txdata;
        struct buff *buf;
        const char *key;
        const char *val;
        size_t klen;
        size_t vlen;
        char *err = NULL;

        key = leveldb_iter_key(iter, &klen);
        txkey = txdb_deserialize_tx_key(key, klen);

        if (txkey == NULL || uint256_issame(txHash, &txkey->txHash) == 0) {
            free(txkey);
            leveldb_iter_next(iter);
            continue;
        }

        NOT_TESTED();

        val = leveldb_iter_value(iter, &vlen);
        txdata = txdb_deserialize_tx_data(val, vlen);
        ASSERT(uint256_iszero(&txdata->blkHash));
        ASSERT(txdata->timestamp != 0);
        memcpy(&txdata->blkHash, blkHash, sizeof *blkHash);

        buf = txdb_serialize_tx_data(txdata);

        leveldb_put(txdb->db, txdb->wr_opts, key, klen,
                    buff_base(buf), buff_curlen(buf), &err);
        buff_free(buf);
        if (err) {
            Warning(LGPFX" failed to write tx entry: %s\n", err);
        }

        txdb_export_tx_info(txdb);

        free(txkey);
        free(txdata->buf);
        free(txdata);
        break;
    }
    leveldb_iter_destroy(iter);
}