Basically, `devtools/reduce-includes.sh */*.c`. Build time from make clean (RUST=0) (includes building external libs): Before: real 0m38.944000-40.416000(40.1131+/-0.4)s user 3m6.790000-17.159000(15.0571+/-2.8)s sys 0m35.304000-37.336000(36.8942+/-0.57)s After: real 0m37.872000-39.974000(39.5466+/-0.59)s user 3m1.211000-14.968000(12.4556+/-3.9)s sys 0m35.008000-36.830000(36.4143+/-0.5)s Build time after touch config.vars (RUST=0): Before: real 0m19.831000-21.862000(21.5528+/-0.58)s user 2m15.361000-30.731000(28.4798+/-4.4)s sys 0m21.056000-22.339000(22.0346+/-0.35)s After: real 0m18.384000-21.307000(20.8605+/-0.92)s user 2m5.585000-26.843000(23.6017+/-6.7)s sys 0m19.650000-22.003000(21.4943+/-0.69)s Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
172 lines
4.2 KiB
C
172 lines
4.2 KiB
C
#include "config.h"
|
|
#include <assert.h>
|
|
#include <bitcoin/psbt.h>
|
|
#include <bitcoin/script.h>
|
|
#include <common/psbt_internal.h>
|
|
#include <common/psbt_open.h>
|
|
#include <common/utils.h>
|
|
#include <wire/peer_wire.h>
|
|
|
|
|
|
static bool next_size(const u8 **cursor, size_t *max, size_t *size)
|
|
{
|
|
size_t len;
|
|
varint_t varint;
|
|
|
|
if (*max < 1)
|
|
return false;
|
|
|
|
len = varint_get(*cursor, *max, &varint);
|
|
|
|
if (len < 1)
|
|
return false;
|
|
|
|
if (*max < len) {
|
|
*max = 0;
|
|
return false;
|
|
}
|
|
|
|
*cursor += len;
|
|
*max -= len;
|
|
*size = varint;
|
|
return true;
|
|
}
|
|
|
|
static u8 *next_script(const tal_t *ctx, const u8 **cursor, size_t *max)
|
|
{
|
|
const u8 *p;
|
|
size_t size;
|
|
u8 *ret;
|
|
|
|
if (!next_size(cursor, max, &size))
|
|
return NULL;
|
|
|
|
if (*max < size) {
|
|
*max = 0;
|
|
return NULL;
|
|
}
|
|
|
|
p = *cursor;
|
|
*max -= size;
|
|
*cursor += size;
|
|
|
|
ret = tal_arr(ctx, u8, size);
|
|
memcpy(ret, p, size);
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
psbt_input_set_final_witness_stack(const tal_t *ctx,
|
|
struct wally_psbt_input *in,
|
|
const struct witness *witness)
|
|
{
|
|
u8 *script, *sctx;
|
|
const u8 *data = witness->witness_data;
|
|
size_t size, max = tal_count(data);
|
|
bool ok;
|
|
|
|
wally_psbt_input_set_final_witness(in, NULL);
|
|
|
|
/* FIXME: return an error?? */
|
|
if (!next_size(&data, &max, &size))
|
|
return;
|
|
|
|
tal_wally_start();
|
|
sctx = tal(NULL, u8);
|
|
|
|
wally_tx_witness_stack_init_alloc(size, &in->final_witness);
|
|
|
|
while ((script = next_script(sctx, &data, &max)) && script != NULL) {
|
|
ok = (wally_tx_witness_stack_add(in->final_witness,
|
|
script, tal_count(script)) == WALLY_OK);
|
|
assert(ok);
|
|
}
|
|
|
|
tal_wally_end(ctx);
|
|
tal_free(sctx);
|
|
}
|
|
|
|
void psbt_finalize_input(const tal_t *ctx,
|
|
struct wally_psbt_input *in,
|
|
const struct witness *witness)
|
|
{
|
|
const struct wally_map_item *redeem_script;
|
|
psbt_input_set_final_witness_stack(ctx, in, witness);
|
|
|
|
/* There's this horrible edgecase where we set the final_witnesses
|
|
* directly onto the PSBT, but the input is a P2SH-wrapped input
|
|
* (which has redeemscripts that belong in the scriptsig). Because
|
|
* of how the internal libwally stuff works calling 'finalize'
|
|
* on these just .. ignores it!? Murder. Anyway, here we do a final
|
|
* scriptsig check -- if there's a redeemscript field still around we
|
|
* just go ahead and mush it into the final_scriptsig field. */
|
|
redeem_script = wally_map_get_integer(&in->psbt_fields, /* PSBT_IN_REDEEM_SCRIPT */ 0x04);
|
|
if (redeem_script) {
|
|
u8 *redeemscript = tal_dup_arr(NULL, u8,
|
|
redeem_script->value,
|
|
redeem_script->value_len, 0);
|
|
u8 *final_scriptsig =
|
|
bitcoin_scriptsig_redeem(ctx,
|
|
take(redeemscript));
|
|
tal_wally_start();
|
|
wally_psbt_input_set_final_scriptsig(in, final_scriptsig, tal_bytelen(final_scriptsig));
|
|
wally_psbt_input_set_redeem_script(in, tal_arr(in, u8, 0), 0);
|
|
tal_wally_end(ctx);
|
|
}
|
|
}
|
|
|
|
const struct witness **
|
|
psbt_to_witnesses(const tal_t *ctx,
|
|
const struct wally_psbt *psbt,
|
|
enum tx_role side_to_stack,
|
|
int input_index_to_ignore)
|
|
{
|
|
u64 serial_id;
|
|
const struct witness **witnesses =
|
|
tal_arr(ctx, const struct witness *, 0);
|
|
|
|
for (size_t i = 0; i < psbt->num_inputs; i++) {
|
|
struct wally_tx_witness_stack *wtx_s =
|
|
psbt->inputs[i].final_witness;
|
|
if (!psbt_get_serial_id(&psbt->inputs[i].unknowns,
|
|
&serial_id))
|
|
/* FIXME: throw an error ? */
|
|
return tal_free(witnesses);
|
|
|
|
if (input_index_to_ignore == i)
|
|
continue;
|
|
|
|
/* BOLT #2:
|
|
* - if is the *initiator*:
|
|
* - MUST send even `serial_id`s
|
|
*/
|
|
if (wtx_s && serial_id % 2 == side_to_stack) {
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The `witness_data` is encoded as per bitcoin's
|
|
* wire protocol (a CompactSize number of elements,
|
|
* with each element a CompactSize length and that
|
|
* many bytes following).
|
|
*/
|
|
struct witness *wit = tal(witnesses, struct witness);
|
|
wit->witness_data = tal_arr(wit, u8, 0);
|
|
add_varint(&wit->witness_data, wtx_s->num_items);
|
|
for (size_t j = 0; j < wtx_s->num_items; j++) {
|
|
add_varint(&wit->witness_data, wtx_s->items[j].witness_len);
|
|
if (wtx_s->items[j].witness_len) {
|
|
assert(wtx_s->items[j].witness);
|
|
tal_expand(&wit->witness_data,
|
|
wtx_s->items[j].witness,
|
|
wtx_s->items[j].witness_len);
|
|
}
|
|
}
|
|
|
|
tal_arr_expand(&witnesses, wit);
|
|
}
|
|
|
|
}
|
|
|
|
return witnesses;
|
|
}
|