Files
lightning/bitcoin/block.c
Christian Decker c99786e720 bitcoin: Use the block hash we computed while deserializing it
Since we now compute the hash while deserializing the block header we can now
just use it, no reason to serialize the header just to hash it again. This
also allows us to throw away all the added dynafed fields in the next commit
instead of having to carry them around.
2020-01-28 20:03:55 +01:00

125 lines
3.5 KiB
C

#include "bitcoin/block.h"
#include "bitcoin/pullpush.h"
#include "bitcoin/tx.h"
#include <ccan/str/hex/hex.h>
#include <common/type_to_string.h>
static void sha256_varint(struct sha256_ctx *ctx, u64 val)
{
u8 vt[VARINT_MAX_LEN];
size_t vtlen;
vtlen = varint_put(vt, val);
sha256_update(ctx, vt, vtlen);
}
/* Encoding is <blockhdr> <varint-num-txs> <tx>... */
struct bitcoin_block *
bitcoin_block_from_hex(const tal_t *ctx, const struct chainparams *chainparams,
const char *hex, size_t hexlen)
{
struct bitcoin_block *b;
u8 *linear_tx;
const u8 *p;
size_t len, i, num;
struct sha256_ctx shactx;
if (hexlen && hex[hexlen-1] == '\n')
hexlen--;
/* Set up the block for success. */
b = tal(ctx, struct bitcoin_block);
/* De-hex the array. */
len = hex_data_size(hexlen);
p = linear_tx = tal_arr(ctx, u8, len);
if (!hex_decode(hex, hexlen, linear_tx, len))
return tal_free(b);
sha256_init(&shactx);
b->hdr.version = pull_le32(&p, &len);
sha256_le32(&shactx, b->hdr.version);
pull(&p, &len, &b->hdr.prev_hash, sizeof(b->hdr.prev_hash));
sha256_update(&shactx, &b->hdr.prev_hash, sizeof(b->hdr.prev_hash));
pull(&p, &len, &b->hdr.merkle_hash, sizeof(b->hdr.merkle_hash));
sha256_update(&shactx, &b->hdr.merkle_hash, sizeof(b->hdr.merkle_hash));
b->hdr.timestamp = pull_le32(&p, &len);
sha256_le32(&shactx, b->hdr.timestamp);
if (is_elements(chainparams)) {
b->elements_hdr = tal(b, struct elements_block_hdr);
b->elements_hdr->block_height = pull_le32(&p, &len);
sha256_le32(&shactx, b->elements_hdr->block_height);
size_t challenge_len = pull_varint(&p, &len);
sha256_varint(&shactx, challenge_len);
sha256_update(&shactx, p, challenge_len);
b->elements_hdr->proof.challenge = tal_arr(b->elements_hdr, u8, challenge_len);
pull(&p, &len, b->elements_hdr->proof.challenge, challenge_len);
size_t solution_len = pull_varint(&p, &len);
b->elements_hdr->proof.solution = tal_arr(b->elements_hdr, u8, solution_len);
pull(&p, &len, b->elements_hdr->proof.solution, solution_len);
} else {
b->hdr.target = pull_le32(&p, &len);
sha256_le32(&shactx, b->hdr.target);
b->hdr.nonce = pull_le32(&p, &len);
sha256_le32(&shactx, b->hdr.nonce);
}
sha256_double_done(&shactx, &b->hdr.hash.shad);
num = pull_varint(&p, &len);
b->tx = tal_arr(b, struct bitcoin_tx *, num);
for (i = 0; i < num; i++) {
b->tx[i] = pull_bitcoin_tx(b->tx, &p, &len);
b->tx[i]->chainparams = chainparams;
}
/* We should end up not overrunning, nor have extra */
if (!p || len)
return tal_free(b);
tal_free(linear_tx);
return b;
}
void bitcoin_block_blkid(const struct bitcoin_block *b,
struct bitcoin_blkid *out)
{
*out = b->hdr.hash;
}
/* We do the same hex-reversing crud as txids. */
bool bitcoin_blkid_from_hex(const char *hexstr, size_t hexstr_len,
struct bitcoin_blkid *blockid)
{
struct bitcoin_txid fake_txid;
if (!bitcoin_txid_from_hex(hexstr, hexstr_len, &fake_txid))
return false;
blockid->shad = fake_txid.shad;
return true;
}
bool bitcoin_blkid_to_hex(const struct bitcoin_blkid *blockid,
char *hexstr, size_t hexstr_len)
{
struct bitcoin_txid fake_txid;
fake_txid.shad = blockid->shad;
return bitcoin_txid_to_hex(&fake_txid, hexstr, hexstr_len);
}
static char *fmt_bitcoin_blkid(const tal_t *ctx,
const struct bitcoin_blkid *blkid)
{
char *hexstr = tal_arr(ctx, char, hex_str_size(sizeof(*blkid)));
bitcoin_blkid_to_hex(blkid, hexstr, hex_str_size(sizeof(*blkid)));
return hexstr;
}
REGISTER_TYPE_TO_STRING(bitcoin_blkid, fmt_bitcoin_blkid);