Exemple #1
0
static int blockstore_find_alternate_chain_height(struct blockstore *bs,
                                                  struct blockentry *be) {
  struct blockentry *prev;
  int height;

  mutex_lock(bs->lock);

  if (be->height > 0) {
    mutex_unlock(bs->lock);
    return be->height;
  }

  ASSERT(be->height == -1);  // orphan

  prev = blockstore_lookup(bs, &be->header.prevBlock);
  if (prev == NULL) {
    mutex_unlock(bs->lock);
    return 0;
  }

  height = 1 + blockstore_find_alternate_chain_height(bs, prev);

  mutex_unlock(bs->lock);

  return height;
}
Exemple #2
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;
}
Exemple #3
0
time_t blockstore_get_block_timestamp(const struct blockstore *bs,
                                      const uint256 *hash) {
  struct blockentry *be;
  time_t ts = 0;

  mutex_lock(bs->lock);

  if (uint256_iszero(hash)) {
    goto done;
  }

  be = blockstore_lookup(bs, hash);
  if (be == NULL) {
    char hashStr[80];

    uint256_snprintf_reverse(hashStr, sizeof hashStr, hash);
    Panic(LGPFX " block %s not found.\n", hashStr);
  }

  ts = be->header.timestamp;

done:
  mutex_unlock(bs->lock);

  return ts;
}
Exemple #4
0
static int
blockstore_set_chain_links(struct blockstore *bs,
                           struct blockentry *be)
{
   struct blockentry *prev;
   char hashStr[80];
   uint256 hash;
   bool s;

   hash256_calc(&be->header, sizeof be->header, &hash);
   uint256_snprintf_reverse(hashStr, sizeof hashStr, &hash);

   if (be->height >= 0) {
      struct blockentry *li;
      /*
       * We've reached the junction with the current/old best chain. All the
       * entries from now on need to be made orphans.
       */

      Log(LGPFX" Reached block %s\n", hashStr);

      li = be->next;
      while (li) {
         hash256_calc(&li->header, sizeof li->header, &hash);
         uint256_snprintf_reverse(hashStr, sizeof hashStr, &hash);
         Log(LGPFX" moving #%d %s from blk -> orphan\n", li->height, hashStr);
         s = hashtable_remove(bs->hash_blk, &hash, sizeof hash);
         ASSERT(s);
         li->height = -1;
         s = hashtable_insert(bs->hash_orphans, &hash, sizeof hash, li);
         ASSERT(s);
         li = li->next;
      }

      return be->height;
   }

   ASSERT(be->height == -1); // orphan

   prev = blockstore_lookup(bs, &be->header.prevBlock);
   ASSERT(prev);

   be->height = 1 + blockstore_set_chain_links(bs, prev);

   Log(LGPFX" moving #%d %s from orphan -> blk\n", be->height, hashStr);

   prev->next = be;
   be->prev = prev;

   s = hashtable_remove(bs->hash_orphans, &hash, sizeof hash);
   ASSERT(s);
   s = hashtable_insert(bs->hash_blk, &hash, sizeof hash, be);
   ASSERT(s);

   return be->height;
}
Exemple #5
0
time_t
blockstore_get_block_timestamp(const struct blockstore *bs,
                               const uint256 *hash)
{
   struct blockentry *be;

   if (uint256_iszero(hash)) {
      return 0;
   }

   be = blockstore_lookup(bs, hash);
   if (be == NULL) {
      char hashStr[80];

      uint256_snprintf_reverse(hashStr, sizeof hashStr, hash);
      Warning(LGPFX" block %s not found.\n", hashStr);
      ASSERT(0);
      return 0;
   }

   return be->header.timestamp;
}