mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-03 20:44:54 +01:00
2ab41af8e2
most likely unused since the switch to libwally for internal blockchain things. these method names were clashing with ones that are to be introduced with some libwally cleanups, so getting rid of them pre-emptively keeps us libwally compatible
283 lines
7.0 KiB
C
283 lines
7.0 KiB
C
#include <assert.h>
|
|
#include <bitcoin/block.h>
|
|
#include <bitcoin/chainparams.h>
|
|
#include <bitcoin/tx.h>
|
|
#include <ccan/mem/mem.h>
|
|
#include <ccan/str/hex/hex.h>
|
|
#include <common/type_to_string.h>
|
|
#include <wire/wire.h>
|
|
|
|
/* Sets *cursor to NULL and returns NULL when a pull fails. */
|
|
static const u8 *pull(const u8 **cursor, size_t *max, void *copy, size_t n)
|
|
{
|
|
const u8 *p = *cursor;
|
|
|
|
if (*max < n) {
|
|
*cursor = NULL;
|
|
*max = 0;
|
|
/* Just make sure we don't leak uninitialized mem! */
|
|
if (copy)
|
|
memset(copy, 0, n);
|
|
return NULL;
|
|
}
|
|
*cursor += n;
|
|
*max -= n;
|
|
assert(p);
|
|
if (copy)
|
|
memcpy(copy, p, n);
|
|
return memcheck(p, n);
|
|
}
|
|
|
|
static u32 pull_le32(const u8 **cursor, size_t *max)
|
|
{
|
|
le32 ret;
|
|
|
|
if (!pull(cursor, max, &ret, sizeof(ret)))
|
|
return 0;
|
|
return le32_to_cpu(ret);
|
|
}
|
|
|
|
static u64 pull_varint(const u8 **cursor, size_t *max)
|
|
{
|
|
u64 ret;
|
|
size_t len;
|
|
|
|
len = varint_get(*cursor, *max, &ret);
|
|
if (len == 0) {
|
|
*cursor = NULL;
|
|
*max = 0;
|
|
return 0;
|
|
}
|
|
pull(cursor, max, NULL, len);
|
|
return ret;
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
static void bitcoin_block_pull_dynafed_params(const u8 **cursor, size_t *len, struct sha256_ctx *shactx)
|
|
{
|
|
u8 type;
|
|
u64 l1, l2;
|
|
pull(cursor, len, &type, 1);
|
|
sha256_update(shactx, &type, 1);
|
|
switch ((enum dynafed_params_type)type) {
|
|
case DYNAFED_PARAMS_NULL:
|
|
break;
|
|
case DYNAFED_PARAMS_COMPACT:
|
|
/* "scriptPubKey" used for block signing */
|
|
l1 = pull_varint(cursor, len);
|
|
sha256_varint(shactx, l1);
|
|
sha256_update(shactx, *cursor, l1);
|
|
pull(cursor, len, NULL, l1);
|
|
|
|
/* signblock_witness_limit */
|
|
sha256_update(shactx, *cursor, 4);
|
|
pull(cursor, len, NULL, 4);
|
|
|
|
/* Skip elided_root */
|
|
sha256_update(shactx, *cursor, 32);
|
|
pull(cursor, len, NULL, 32);
|
|
break;
|
|
|
|
case DYNAFED_PARAMS_FULL:
|
|
/* "scriptPubKey" used for block signing */
|
|
l1 = pull_varint(cursor, len);
|
|
sha256_varint(shactx, l1);
|
|
sha256_update(shactx, *cursor, l1);
|
|
pull(cursor, len, NULL, l1);
|
|
|
|
/* signblock_witness_limit */
|
|
sha256_update(shactx, *cursor, 4);
|
|
pull(cursor, len, NULL, 4);
|
|
|
|
/* fedpeg_program */
|
|
l1 = pull_varint(cursor, len);
|
|
sha256_varint(shactx, l1);
|
|
sha256_update(shactx, *cursor, l1);
|
|
pull(cursor, len, NULL, l1);
|
|
|
|
/* fedpegscript */
|
|
l1 = pull_varint(cursor, len);
|
|
sha256_varint(shactx, l1);
|
|
sha256_update(shactx, *cursor, l1);
|
|
pull(cursor, len, NULL, l1);
|
|
|
|
/* extension space */
|
|
l2 = pull_varint(cursor, len);
|
|
sha256_varint(shactx, l2);
|
|
for (size_t i = 0; i < l2; i++) {
|
|
l1 = pull_varint(cursor, len);
|
|
sha256_varint(shactx, l1);
|
|
sha256_update(shactx, *cursor, l1);
|
|
pull(cursor, len, NULL, l1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void bitcoin_block_pull_dynafed_details(const u8 **cursor, size_t *len, struct sha256_ctx *shactx)
|
|
{
|
|
bitcoin_block_pull_dynafed_params(cursor, len, shactx);
|
|
bitcoin_block_pull_dynafed_params(cursor, len, shactx);
|
|
|
|
/* Consume the signblock_witness */
|
|
u64 numwitnesses = pull_varint(cursor, len);
|
|
for (size_t i=0; i<numwitnesses; i++) {
|
|
u64 witsize = pull_varint(cursor, len);
|
|
pull(cursor, len, NULL, witsize);
|
|
}
|
|
}
|
|
|
|
/* 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, templen;
|
|
struct sha256_ctx shactx;
|
|
bool is_dynafed;
|
|
u32 height;
|
|
|
|
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)) {
|
|
/* A dynafed block is signalled by setting the MSB of the version. */
|
|
is_dynafed = (b->hdr.version >> 31 == 1);
|
|
|
|
/* elements_header.height */
|
|
height = pull_le32(&p, &len);
|
|
sha256_le32(&shactx, height);
|
|
|
|
if (is_dynafed) {
|
|
bitcoin_block_pull_dynafed_details(&p, &len, &shactx);
|
|
} else {
|
|
/* elemens_header.challenge */
|
|
templen = pull_varint(&p, &len);
|
|
sha256_varint(&shactx, templen);
|
|
sha256_update(&shactx, p, templen);
|
|
pull(&p, &len, NULL, templen);
|
|
|
|
/* elements_header.solution. Not hashed since it'd be
|
|
* a circular dependency. */
|
|
templen = pull_varint(&p, &len);
|
|
pull(&p, &len, NULL, templen);
|
|
}
|
|
|
|
} 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);
|
|
|
|
void fromwire_bitcoin_blkid(const u8 **cursor, size_t *max,
|
|
struct bitcoin_blkid *blkid)
|
|
{
|
|
fromwire_sha256_double(cursor, max, &blkid->shad);
|
|
}
|
|
|
|
void towire_bitcoin_blkid(u8 **pptr, const struct bitcoin_blkid *blkid)
|
|
{
|
|
towire_sha256_double(pptr, &blkid->shad);
|
|
}
|
|
|
|
|
|
void towire_chainparams(u8 **cursor, const struct chainparams *chainparams)
|
|
{
|
|
towire_bitcoin_blkid(cursor, &chainparams->genesis_blockhash);
|
|
}
|
|
|
|
void fromwire_chainparams(const u8 **cursor, size_t *max,
|
|
const struct chainparams **chainparams)
|
|
{
|
|
struct bitcoin_blkid genesis;
|
|
fromwire_bitcoin_blkid(cursor, max, &genesis);
|
|
*chainparams = chainparams_by_chainhash(&genesis);
|
|
}
|