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; }
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; }
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; }
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; }
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; }