Esempio n. 1
0
static bool bp_block_valid_target(struct bp_block *block)
{
	BIGNUM target, sha256;
	BN_init(&target);
	BN_init(&sha256);

	u256_from_compact(&target, block->nBits);
	bu256_bn(&sha256, &block->sha256);

	int cmp = BN_cmp(&sha256, &target);

	BN_clear_free(&target);
	BN_clear_free(&sha256);

	if (cmp > 0)			/* sha256 > target */
		return false;

	return true;
}
Esempio n. 2
0
static bool blkdb_connect(struct blkdb *db, struct blkinfo *bi,
			  struct blkdb_reorg *reorg_info)
{
	memset(reorg_info, 0, sizeof(*reorg_info));

	if (blkdb_lookup(db, &bi->hash))
		return false;

	bool rc = false;
	BIGNUM cur_work;
	BN_init(&cur_work);

	u256_from_compact(&cur_work, bi->hdr.nBits);

	bool best_chain = false;

	/* verify genesis block matches first record */
	if (bp_hashtab_size(db->blocks) == 0) {
		if (!bu256_equal(&bi->hdr.sha256, &db->block0))
			goto out;

		/* bi->prev = NULL; */
		bi->height = 0;

		BN_copy(&bi->work, &cur_work);

		best_chain = true;
	}

	/* lookup and verify previous block */
	else {
		struct blkinfo *prev = blkdb_lookup(db, &bi->hdr.hashPrevBlock);
		if (!prev)
			goto out;

		bi->prev = prev;
		bi->height = prev->height + 1;

		if (!BN_add(&bi->work, &cur_work, &prev->work))
			goto out;

		if (BN_cmp(&bi->work, &db->best_chain->work) > 0)
			best_chain = true;
	}

	/* add to block map */
	bp_hashtab_put(db->blocks, &bi->hash, bi);

	/* if new best chain found, update pointers */
	if (best_chain) {
		struct blkinfo *old_best = db->best_chain;
		struct blkinfo *new_best = bi;

		reorg_info->old_best = old_best;

		/* likely case: new best chain has greater height */
		if (!old_best) {
			while (new_best) {
				new_best = new_best->prev;
				reorg_info->conn++;
			}
		} else {
			while (new_best &&
			       (new_best->height > old_best->height)) {
				new_best = new_best->prev;
				reorg_info->conn++;
			}
		}

		/* unlikely case: old best chain has greater height */
		while (old_best && new_best &&
		       (old_best->height > new_best->height)) {
			old_best = old_best->prev;
			reorg_info->disconn++;
		}

		/* height matches, but we are still walking parallel chains */
		while (old_best && new_best && (old_best != new_best)) {
			new_best = new_best->prev;
			reorg_info->conn++;

			old_best = old_best->prev;
			reorg_info->disconn++;
		}

		/* reorg analyzed. update database's best-chain pointer */
		db->best_chain = bi;
	}

	rc = true;

out:
	BN_clear_free(&cur_work);
	return rc;
}