2016-01-21 21:08:08 +01:00
|
|
|
#include <assert.h>
|
2017-08-28 18:02:01 +02:00
|
|
|
#include <bitcoin/block.h>
|
2020-05-16 03:29:05 +02:00
|
|
|
#include <bitcoin/chainparams.h>
|
2020-05-21 03:57:00 +02:00
|
|
|
#include <bitcoin/psbt.h>
|
2020-05-27 03:37:44 +02:00
|
|
|
#include <bitcoin/script.h>
|
2017-08-28 18:02:01 +02:00
|
|
|
#include <bitcoin/tx.h>
|
2016-01-21 21:11:46 +01:00
|
|
|
#include <ccan/cast/cast.h>
|
2015-05-28 23:38:27 +02:00
|
|
|
#include <ccan/crypto/sha256/sha256.h>
|
2015-06-12 04:56:59 +02:00
|
|
|
#include <ccan/endian/endian.h>
|
2015-10-26 11:35:28 +01:00
|
|
|
#include <ccan/mem/mem.h>
|
2015-07-01 06:14:31 +02:00
|
|
|
#include <ccan/read_write_all/read_write_all.h>
|
2015-06-04 06:18:11 +02:00
|
|
|
#include <ccan/str/hex/hex.h>
|
2017-08-28 18:02:01 +02:00
|
|
|
#include <common/type_to_string.h>
|
2016-01-21 21:11:46 +01:00
|
|
|
#include <stdio.h>
|
2019-06-21 02:11:41 +02:00
|
|
|
#include <wire/wire.h>
|
2015-05-28 23:38:27 +02:00
|
|
|
|
2016-04-11 09:09:53 +02:00
|
|
|
#define SEGREGATED_WITNESS_FLAG 0x1
|
|
|
|
|
2020-05-27 03:41:31 +02:00
|
|
|
/* FIXME: When wally exposes this, we will clash and can remove this one */
|
|
|
|
int wally_tx_clone(struct wally_tx *tx, struct wally_tx **output)
|
|
|
|
{
|
|
|
|
u8 *txlin = linearize_wtx(NULL, tx);
|
|
|
|
int flags = WALLY_TX_FLAG_USE_WITNESS;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (chainparams->is_elements)
|
|
|
|
flags |= WALLY_TX_FLAG_USE_ELEMENTS;
|
|
|
|
|
|
|
|
ret = wally_tx_from_bytes(txlin, tal_bytelen(txlin), flags, output);
|
|
|
|
tal_free(txlin);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-09-17 02:08:05 +02:00
|
|
|
struct bitcoin_tx_output *new_tx_output(const tal_t *ctx,
|
|
|
|
struct amount_sat amount,
|
|
|
|
const u8 *script)
|
|
|
|
{
|
|
|
|
struct bitcoin_tx_output *output = tal(ctx, struct bitcoin_tx_output);
|
|
|
|
output->amount = amount;
|
|
|
|
output->script = tal_dup_arr(output, u8, script, tal_count(script), 0);
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2019-06-05 07:28:55 +02:00
|
|
|
int bitcoin_tx_add_output(struct bitcoin_tx *tx, const u8 *script,
|
2020-05-21 03:57:00 +02:00
|
|
|
u8 *wscript, struct amount_sat amount)
|
2019-03-14 16:20:03 +01:00
|
|
|
{
|
2019-03-25 17:08:29 +01:00
|
|
|
size_t i = tx->wtx->num_outputs;
|
2019-03-14 16:20:03 +01:00
|
|
|
struct wally_tx_output *output;
|
2020-05-21 03:57:00 +02:00
|
|
|
struct wally_psbt_output *psbt_out;
|
2019-05-06 15:20:47 +02:00
|
|
|
int ret;
|
|
|
|
u64 satoshis = amount.satoshis; /* Raw: low-level helper */
|
2019-07-30 21:09:47 +02:00
|
|
|
const struct chainparams *chainparams = tx->chainparams;
|
2019-03-25 13:52:31 +01:00
|
|
|
assert(i < tx->wtx->outputs_allocation_len);
|
2019-03-14 16:20:03 +01:00
|
|
|
|
|
|
|
assert(tx->wtx != NULL);
|
2019-07-30 21:09:47 +02:00
|
|
|
assert(chainparams);
|
2019-05-06 15:20:47 +02:00
|
|
|
|
2019-09-26 00:42:26 +02:00
|
|
|
if (chainparams->is_elements) {
|
2019-05-06 15:20:47 +02:00
|
|
|
u8 value[9];
|
|
|
|
ret = wally_tx_confidential_value_from_satoshi(satoshis, value,
|
|
|
|
sizeof(value));
|
|
|
|
assert(ret == WALLY_OK);
|
|
|
|
ret = wally_tx_elements_output_init_alloc(
|
2019-07-30 21:09:47 +02:00
|
|
|
script, tal_bytelen(script), chainparams->fee_asset_tag, 33,
|
|
|
|
value, sizeof(value), NULL, 0, NULL, 0, NULL, 0, &output);
|
2019-05-06 15:20:47 +02:00
|
|
|
assert(ret == WALLY_OK);
|
|
|
|
/* Cheat a bit by also setting the numeric satoshi value,
|
|
|
|
* otherwise we end up converting a number of times */
|
|
|
|
output->satoshi = satoshis;
|
|
|
|
} else {
|
|
|
|
ret = wally_tx_output_init_alloc(satoshis, script,
|
|
|
|
tal_bytelen(script), &output);
|
2019-10-07 00:25:23 +02:00
|
|
|
assert(ret == WALLY_OK);
|
2019-05-06 15:20:47 +02:00
|
|
|
}
|
|
|
|
ret = wally_tx_add_output(tx->wtx, output);
|
|
|
|
assert(ret == WALLY_OK);
|
|
|
|
|
2020-05-21 03:57:00 +02:00
|
|
|
psbt_out = psbt_add_output(tx->psbt, output, i);
|
|
|
|
if (wscript) {
|
|
|
|
ret = wally_psbt_output_set_witness_script(psbt_out,
|
|
|
|
wscript,
|
|
|
|
tal_bytelen(wscript));
|
|
|
|
assert(ret == WALLY_OK);
|
|
|
|
}
|
|
|
|
|
2019-03-14 16:20:03 +01:00
|
|
|
wally_tx_output_free(output);
|
2019-05-06 15:20:47 +02:00
|
|
|
bitcoin_tx_output_set_amount(tx, i, amount);
|
2019-03-14 16:20:03 +01:00
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2019-08-12 21:02:06 +02:00
|
|
|
int bitcoin_tx_add_multi_outputs(struct bitcoin_tx *tx,
|
|
|
|
struct bitcoin_tx_output **outputs)
|
|
|
|
{
|
|
|
|
for (size_t j = 0; j < tal_count(outputs); j++)
|
|
|
|
bitcoin_tx_add_output(tx, outputs[j]->script,
|
2020-05-21 03:57:00 +02:00
|
|
|
NULL, outputs[j]->amount);
|
2019-08-12 21:02:06 +02:00
|
|
|
|
|
|
|
return tx->wtx->num_outputs;
|
|
|
|
}
|
|
|
|
|
2020-04-02 03:34:00 +02:00
|
|
|
bool elements_tx_output_is_fee(const struct bitcoin_tx *tx, int outnum)
|
2019-05-09 18:49:46 +02:00
|
|
|
{
|
|
|
|
assert(outnum < tx->wtx->num_outputs);
|
2019-09-26 00:42:26 +02:00
|
|
|
return chainparams->is_elements &&
|
|
|
|
tx->wtx->outputs[outnum].script_len == 0;
|
2019-05-09 18:49:46 +02:00
|
|
|
}
|
|
|
|
|
2020-04-02 03:35:04 +02:00
|
|
|
struct amount_sat bitcoin_tx_compute_fee_w_inputs(const struct bitcoin_tx *tx,
|
|
|
|
struct amount_sat input_val)
|
2019-05-06 15:24:53 +02:00
|
|
|
{
|
2019-09-26 21:07:20 +02:00
|
|
|
struct amount_asset asset;
|
2019-09-26 12:25:05 +02:00
|
|
|
bool ok;
|
2019-05-06 15:24:53 +02:00
|
|
|
|
2019-09-26 12:25:05 +02:00
|
|
|
for (size_t i = 0; i < tx->wtx->num_outputs; i++) {
|
2019-09-26 21:07:20 +02:00
|
|
|
asset = bitcoin_tx_output_get_amount(tx, i);
|
|
|
|
if (elements_tx_output_is_fee(tx, i) ||
|
|
|
|
!amount_asset_is_main(&asset))
|
2019-05-09 18:49:46 +02:00
|
|
|
continue;
|
|
|
|
|
2020-04-02 03:35:04 +02:00
|
|
|
ok = amount_sat_sub(&input_val, input_val,
|
|
|
|
amount_asset_to_sat(&asset));
|
2020-06-17 00:07:28 +02:00
|
|
|
if (!ok)
|
|
|
|
return AMOUNT_SAT(0);
|
|
|
|
|
2019-05-06 15:24:53 +02:00
|
|
|
}
|
2020-04-02 03:35:04 +02:00
|
|
|
return input_val;
|
2019-05-06 15:24:53 +02:00
|
|
|
}
|
|
|
|
|
2020-02-08 21:30:03 +01:00
|
|
|
/**
|
2020-04-02 03:35:04 +02:00
|
|
|
* Compute how much fee we are actually sending with this transaction.
|
|
|
|
*/
|
|
|
|
struct amount_sat bitcoin_tx_compute_fee(const struct bitcoin_tx *tx)
|
|
|
|
{
|
2020-05-27 03:37:44 +02:00
|
|
|
struct amount_sat input_total = AMOUNT_SAT(0), input_amt;
|
2020-04-02 03:35:04 +02:00
|
|
|
bool ok;
|
|
|
|
|
2020-05-27 03:37:44 +02:00
|
|
|
for (size_t i = 0; i < tx->psbt->num_inputs; i++) {
|
|
|
|
input_amt = psbt_input_get_amount(tx->psbt, i);
|
|
|
|
ok = amount_sat_add(&input_total, input_total, input_amt);
|
2020-04-02 03:35:04 +02:00
|
|
|
assert(ok);
|
|
|
|
}
|
|
|
|
|
|
|
|
return bitcoin_tx_compute_fee_w_inputs(tx, input_total);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2020-02-08 21:30:03 +01:00
|
|
|
* Add an explicit fee output if necessary.
|
|
|
|
*
|
|
|
|
* An explicit fee output is only necessary if we are using an elements
|
|
|
|
* transaction, and we have a non-zero fee. This method may be called multiple
|
|
|
|
* times.
|
|
|
|
*
|
|
|
|
* Returns the position of the fee output, or -1 in the case of non-elements
|
|
|
|
* transactions.
|
|
|
|
*/
|
|
|
|
static int elements_tx_add_fee_output(struct bitcoin_tx *tx)
|
2019-05-06 15:24:53 +02:00
|
|
|
{
|
2019-09-26 12:25:05 +02:00
|
|
|
struct amount_sat fee = bitcoin_tx_compute_fee(tx);
|
2020-02-08 21:26:55 +01:00
|
|
|
int pos;
|
2019-05-06 15:24:53 +02:00
|
|
|
|
|
|
|
/* If we aren't using elements, we don't add explicit fee outputs */
|
2019-09-26 12:25:05 +02:00
|
|
|
if (!chainparams->is_elements || amount_sat_eq(fee, AMOUNT_SAT(0)))
|
2019-05-06 15:24:53 +02:00
|
|
|
return -1;
|
2019-05-09 18:49:46 +02:00
|
|
|
|
|
|
|
/* Try to find any existing fee output */
|
2020-02-08 21:26:55 +01:00
|
|
|
for (pos = 0; pos < tx->wtx->num_outputs; pos++) {
|
|
|
|
if (elements_tx_output_is_fee(tx, pos))
|
|
|
|
break;
|
2019-05-09 18:49:46 +02:00
|
|
|
}
|
|
|
|
|
2020-05-21 03:57:00 +02:00
|
|
|
if (pos == tx->wtx->num_outputs)
|
|
|
|
return bitcoin_tx_add_output(tx, NULL, NULL, fee);
|
|
|
|
else {
|
2019-05-09 18:49:46 +02:00
|
|
|
bitcoin_tx_output_set_amount(tx, pos, fee);
|
|
|
|
return pos;
|
|
|
|
}
|
2019-05-06 15:24:53 +02:00
|
|
|
}
|
|
|
|
|
2020-05-22 05:16:11 +02:00
|
|
|
void bitcoin_tx_set_locktime(struct bitcoin_tx *tx, u32 locktime)
|
|
|
|
{
|
|
|
|
tx->wtx->locktime = locktime;
|
|
|
|
tx->psbt->tx->locktime = locktime;
|
|
|
|
}
|
|
|
|
|
2019-03-14 16:20:03 +01:00
|
|
|
int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_txid *txid,
|
2020-05-21 21:46:19 +02:00
|
|
|
u32 outnum, u32 sequence, const u8 *scriptSig,
|
|
|
|
struct amount_sat amount, const u8 *scriptPubkey,
|
|
|
|
const u8 *input_wscript)
|
2019-03-14 16:20:03 +01:00
|
|
|
{
|
|
|
|
struct wally_tx_input *input;
|
2020-05-21 21:42:39 +02:00
|
|
|
int wally_err;
|
2019-09-16 23:58:36 +02:00
|
|
|
size_t i;
|
2019-03-14 16:20:03 +01:00
|
|
|
|
|
|
|
assert(tx->wtx != NULL);
|
2019-09-16 23:58:36 +02:00
|
|
|
i = tx->wtx->num_inputs;
|
2020-05-21 21:42:39 +02:00
|
|
|
wally_err = wally_tx_input_init_alloc(txid->shad.sha.u.u8,
|
|
|
|
sizeof(struct bitcoin_txid),
|
|
|
|
outnum, sequence,
|
2020-05-21 21:46:19 +02:00
|
|
|
scriptSig, tal_bytelen(scriptSig),
|
2020-05-21 21:42:39 +02:00
|
|
|
NULL /* Empty witness stack */,
|
|
|
|
&input);
|
|
|
|
assert(wally_err == WALLY_OK);
|
2019-09-26 00:42:26 +02:00
|
|
|
input->features = chainparams->is_elements ? WALLY_TX_IS_ELEMENTS : 0;
|
2019-03-14 16:20:03 +01:00
|
|
|
wally_tx_add_input(tx->wtx, input);
|
2020-05-21 03:57:00 +02:00
|
|
|
psbt_add_input(tx->psbt, input, i);
|
2019-03-14 16:20:03 +01:00
|
|
|
|
2020-05-21 21:46:19 +02:00
|
|
|
if (input_wscript) {
|
|
|
|
/* Add the prev output's data into the PSBT struct */
|
|
|
|
psbt_input_set_prev_utxo_wscript(tx->psbt, i, input_wscript, amount);
|
|
|
|
} else if (scriptPubkey) {
|
|
|
|
if (is_p2wsh(scriptPubkey, NULL) || is_p2wpkh(scriptPubkey, NULL) ||
|
|
|
|
/* FIXME: assert that p2sh inputs are witness/are accompanied by a redeemscript+witnessscript */
|
|
|
|
is_p2sh(scriptPubkey, NULL)) {
|
|
|
|
/* the only way to get here currently with a p2sh script is via a p2sh-p2wpkh script
|
|
|
|
* that we've created ...*/
|
|
|
|
/* Relevant section from bip-0174, emphasis mine:
|
|
|
|
* ** Value: The entire transaction output in network serialization which the current input spends from.
|
|
|
|
* This should only be present for inputs which spend segwit outputs, _including P2SH embedded ones._
|
|
|
|
*/
|
|
|
|
psbt_input_set_prev_utxo(tx->psbt, i, scriptPubkey, amount);
|
|
|
|
}
|
|
|
|
}
|
2019-03-22 14:01:16 +01:00
|
|
|
|
2020-05-27 03:37:44 +02:00
|
|
|
wally_tx_input_free(input);
|
2020-05-21 03:57:00 +02:00
|
|
|
|
2019-03-14 16:20:03 +01:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2019-03-15 14:09:11 +01:00
|
|
|
bool bitcoin_tx_check(const struct bitcoin_tx *tx)
|
|
|
|
{
|
|
|
|
u8 *newtx;
|
|
|
|
size_t written;
|
2019-05-06 15:24:53 +02:00
|
|
|
int flags = WALLY_TX_FLAG_USE_WITNESS;
|
2019-03-15 14:09:11 +01:00
|
|
|
|
2019-05-06 15:24:53 +02:00
|
|
|
if (wally_tx_get_length(tx->wtx, flags, &written) != WALLY_OK)
|
2019-03-15 14:09:11 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
newtx = tal_arr(tmpctx, u8, written);
|
2019-05-06 15:24:53 +02:00
|
|
|
if (wally_tx_to_bytes(tx->wtx, flags, newtx, written, &written) !=
|
|
|
|
WALLY_OK)
|
2019-03-15 14:09:11 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (written != tal_bytelen(newtx))
|
|
|
|
return false;
|
|
|
|
|
2019-03-25 13:52:31 +01:00
|
|
|
return true;
|
2019-03-15 14:09:11 +01:00
|
|
|
}
|
|
|
|
|
2019-03-20 16:41:29 +01:00
|
|
|
void bitcoin_tx_output_set_amount(struct bitcoin_tx *tx, int outnum,
|
2019-08-21 05:52:44 +02:00
|
|
|
struct amount_sat amount)
|
2019-03-20 16:41:29 +01:00
|
|
|
{
|
2019-04-16 22:30:25 +02:00
|
|
|
u64 satoshis = amount.satoshis; /* Raw: low-level helper */
|
|
|
|
struct wally_tx_output *output = &tx->wtx->outputs[outnum];
|
2019-03-25 17:08:29 +01:00
|
|
|
assert(outnum < tx->wtx->num_outputs);
|
2019-09-26 00:42:26 +02:00
|
|
|
if (chainparams->is_elements) {
|
|
|
|
int ret = wally_tx_confidential_value_from_satoshi(
|
|
|
|
satoshis, output->value, output->value_len);
|
2019-05-06 15:20:47 +02:00
|
|
|
assert(ret == WALLY_OK);
|
2019-04-16 22:30:25 +02:00
|
|
|
} else {
|
|
|
|
output->satoshi = satoshis;
|
2020-05-21 03:57:00 +02:00
|
|
|
|
|
|
|
/* update the global tx for the psbt also */
|
|
|
|
output = &tx->psbt->tx->outputs[outnum];
|
|
|
|
output->satoshi = satoshis;
|
2019-04-16 22:30:25 +02:00
|
|
|
}
|
2019-03-20 16:41:29 +01:00
|
|
|
}
|
|
|
|
|
2020-06-16 20:40:13 +02:00
|
|
|
const u8 *wally_tx_output_get_script(const tal_t *ctx,
|
|
|
|
const struct wally_tx_output *output)
|
2019-03-22 22:45:41 +01:00
|
|
|
{
|
2019-09-25 14:45:34 +02:00
|
|
|
if (output->script == NULL) {
|
|
|
|
/* This can happen for coinbase transactions and pegin
|
|
|
|
* transactions */
|
2019-04-13 19:14:07 +02:00
|
|
|
return NULL;
|
2019-09-25 14:45:34 +02:00
|
|
|
}
|
2019-04-13 19:14:07 +02:00
|
|
|
|
2020-06-16 20:40:13 +02:00
|
|
|
return tal_dup_arr(ctx, u8, output->script, output->script_len, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
const u8 *bitcoin_tx_output_get_script(const tal_t *ctx,
|
|
|
|
const struct bitcoin_tx *tx, int outnum)
|
|
|
|
{
|
|
|
|
const struct wally_tx_output *output;
|
|
|
|
assert(outnum < tx->wtx->num_outputs);
|
|
|
|
output = &tx->wtx->outputs[outnum];
|
|
|
|
|
|
|
|
return wally_tx_output_get_script(ctx, output);
|
2019-03-22 22:45:41 +01:00
|
|
|
}
|
|
|
|
|
2020-05-21 05:57:54 +02:00
|
|
|
u8 *bitcoin_tx_output_get_witscript(const tal_t *ctx, const struct bitcoin_tx *tx,
|
|
|
|
int outnum)
|
2020-05-21 03:57:00 +02:00
|
|
|
{
|
|
|
|
struct wally_psbt_output *out;
|
2020-05-21 05:57:54 +02:00
|
|
|
|
2020-05-21 03:57:00 +02:00
|
|
|
assert(outnum < tx->psbt->num_outputs);
|
|
|
|
out = &tx->psbt->outputs[outnum];
|
|
|
|
|
|
|
|
if (out->witness_script_len == 0)
|
|
|
|
return NULL;
|
|
|
|
|
2020-05-21 05:57:54 +02:00
|
|
|
return tal_dup_arr(ctx, u8, out->witness_script, out->witness_script_len, 0);
|
2020-05-21 03:57:00 +02:00
|
|
|
}
|
|
|
|
|
2019-09-26 21:07:20 +02:00
|
|
|
struct amount_asset bitcoin_tx_output_get_amount(const struct bitcoin_tx *tx,
|
|
|
|
int outnum)
|
2019-03-22 22:45:41 +01:00
|
|
|
{
|
2019-07-30 21:09:47 +02:00
|
|
|
assert(tx->chainparams);
|
2019-03-22 22:45:41 +01:00
|
|
|
assert(outnum < tx->wtx->num_outputs);
|
2020-05-26 05:39:25 +02:00
|
|
|
return wally_tx_output_get_amount(&tx->wtx->outputs[outnum]);
|
2019-03-22 22:45:41 +01:00
|
|
|
}
|
|
|
|
|
2019-11-14 17:38:17 +01:00
|
|
|
void bitcoin_tx_output_get_amount_sat(struct bitcoin_tx *tx, int outnum,
|
|
|
|
struct amount_sat *amount)
|
|
|
|
{
|
|
|
|
struct amount_asset asset_amt;
|
|
|
|
asset_amt = bitcoin_tx_output_get_amount(tx, outnum);
|
|
|
|
assert(amount_asset_is_main(&asset_amt));
|
|
|
|
*amount = amount_asset_to_sat(&asset_amt);
|
|
|
|
}
|
|
|
|
|
2019-03-20 16:41:29 +01:00
|
|
|
void bitcoin_tx_input_set_witness(struct bitcoin_tx *tx, int innum,
|
|
|
|
u8 **witness)
|
|
|
|
{
|
|
|
|
struct wally_tx_witness_stack *stack = NULL;
|
|
|
|
size_t stack_size = tal_count(witness);
|
|
|
|
|
|
|
|
/* Free any lingering witness */
|
|
|
|
if (witness) {
|
|
|
|
wally_tx_witness_stack_init_alloc(stack_size, &stack);
|
|
|
|
for (size_t i = 0; i < stack_size; i++)
|
|
|
|
wally_tx_witness_stack_add(stack, witness[i],
|
|
|
|
tal_bytelen(witness[i]));
|
|
|
|
}
|
|
|
|
wally_tx_set_input_witness(tx->wtx, innum, stack);
|
2020-05-21 03:57:00 +02:00
|
|
|
|
|
|
|
/* Also add to the psbt */
|
2020-05-29 05:09:59 +02:00
|
|
|
if (stack)
|
|
|
|
wally_psbt_input_set_final_witness(&tx->psbt->inputs[innum], stack);
|
|
|
|
else {
|
|
|
|
/* FIXME: libwally-psbt doesn't allow 'unsetting' of witness via
|
|
|
|
* the set method at the moment, so we do it manually*/
|
|
|
|
struct wally_psbt_input *in = &tx->psbt->inputs[innum];
|
|
|
|
if (in->final_witness)
|
|
|
|
wally_tx_witness_stack_free(in->final_witness);
|
|
|
|
in->final_witness = NULL;
|
2020-05-21 03:57:00 +02:00
|
|
|
}
|
|
|
|
|
2019-03-20 16:41:29 +01:00
|
|
|
if (stack)
|
|
|
|
wally_tx_witness_stack_free(stack);
|
2019-08-21 05:52:42 +02:00
|
|
|
if (taken(witness))
|
|
|
|
tal_free(witness);
|
2019-03-20 16:41:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void bitcoin_tx_input_set_script(struct bitcoin_tx *tx, int innum, u8 *script)
|
|
|
|
{
|
2020-05-21 03:57:00 +02:00
|
|
|
struct wally_psbt_input *in;
|
2019-03-20 16:41:29 +01:00
|
|
|
wally_tx_set_input_script(tx->wtx, innum, script, tal_bytelen(script));
|
2020-05-21 03:57:00 +02:00
|
|
|
|
|
|
|
/* Also add to the psbt */
|
|
|
|
assert(innum < tx->psbt->num_inputs);
|
|
|
|
in = &tx->psbt->inputs[innum];
|
|
|
|
wally_psbt_input_set_final_script_sig(in, script, tal_bytelen(script));
|
2019-03-20 16:41:29 +01:00
|
|
|
}
|
|
|
|
|
2019-03-22 22:45:41 +01:00
|
|
|
const u8 *bitcoin_tx_input_get_witness(const tal_t *ctx,
|
|
|
|
const struct bitcoin_tx *tx, int innum,
|
|
|
|
int witnum)
|
|
|
|
{
|
|
|
|
const u8 *witness_item;
|
|
|
|
struct wally_tx_witness_item *item;
|
|
|
|
assert(innum < tx->wtx->num_inputs);
|
|
|
|
assert(witnum < tx->wtx->inputs[innum].witness->num_items);
|
|
|
|
item = &tx->wtx->inputs[innum].witness->items[witnum];
|
|
|
|
witness_item =
|
|
|
|
tal_dup_arr(ctx, u8, item->witness, item->witness_len, 0);
|
|
|
|
return witness_item;
|
|
|
|
}
|
|
|
|
|
|
|
|
void bitcoin_tx_input_get_txid(const struct bitcoin_tx *tx, int innum,
|
|
|
|
struct bitcoin_txid *out)
|
|
|
|
{
|
|
|
|
assert(innum < tx->wtx->num_inputs);
|
2020-05-26 05:39:25 +02:00
|
|
|
wally_tx_input_get_txid(&tx->wtx->inputs[innum], out);
|
|
|
|
}
|
|
|
|
|
|
|
|
void wally_tx_input_get_txid(const struct wally_tx_input *in,
|
|
|
|
struct bitcoin_txid *txid)
|
|
|
|
{
|
|
|
|
BUILD_ASSERT(sizeof(struct bitcoin_txid) == sizeof(in->txhash));
|
|
|
|
memcpy(txid, in->txhash, sizeof(struct bitcoin_txid));
|
2019-03-22 22:45:41 +01:00
|
|
|
}
|
|
|
|
|
2016-04-11 09:09:53 +02:00
|
|
|
/* BIP144:
|
|
|
|
* If the witness is empty, the old serialization format should be used. */
|
2020-05-26 05:39:25 +02:00
|
|
|
static bool uses_witness(const struct wally_tx *wtx)
|
2016-04-11 09:09:53 +02:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
2020-05-26 05:39:25 +02:00
|
|
|
for (i = 0; i < wtx->num_inputs; i++) {
|
|
|
|
if (wtx->inputs[i].witness)
|
2016-04-11 09:09:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-05-26 05:39:25 +02:00
|
|
|
u8 *linearize_tx(const tal_t *ctx, const struct bitcoin_tx *tx)
|
2015-05-28 23:38:27 +02:00
|
|
|
{
|
2020-05-26 05:39:25 +02:00
|
|
|
return linearize_wtx(ctx, tx->wtx);
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 *linearize_wtx(const tal_t *ctx, const struct wally_tx *wtx)
|
|
|
|
{
|
|
|
|
u8 *arr;
|
|
|
|
u32 flag = 0;
|
2019-03-22 17:52:15 +01:00
|
|
|
size_t len, written;
|
2020-05-26 05:39:25 +02:00
|
|
|
int res;
|
2015-05-28 23:38:27 +02:00
|
|
|
|
2020-05-26 05:39:25 +02:00
|
|
|
if (uses_witness(wtx))
|
2019-03-22 17:52:15 +01:00
|
|
|
flag |= WALLY_TX_FLAG_USE_WITNESS;
|
2016-04-11 09:09:53 +02:00
|
|
|
|
2020-05-26 05:39:25 +02:00
|
|
|
res = wally_tx_get_length(wtx, flag, &len);
|
2019-06-21 02:11:00 +02:00
|
|
|
assert(res == WALLY_OK);
|
2020-05-26 05:39:25 +02:00
|
|
|
arr = tal_arr(ctx, u8, len);
|
|
|
|
res = wally_tx_to_bytes(wtx, flag, arr, len, &written);
|
2019-06-21 02:11:00 +02:00
|
|
|
assert(len == written);
|
2015-06-02 05:46:05 +02:00
|
|
|
|
|
|
|
return arr;
|
2015-05-28 23:38:27 +02:00
|
|
|
}
|
2015-05-29 04:03:18 +02:00
|
|
|
|
2019-07-01 16:02:04 +02:00
|
|
|
size_t bitcoin_tx_weight(const struct bitcoin_tx *tx)
|
2016-04-24 12:23:35 +02:00
|
|
|
{
|
2019-07-01 16:02:04 +02:00
|
|
|
size_t weight;
|
|
|
|
int ret = wally_tx_get_weight(tx->wtx, &weight);
|
|
|
|
assert(ret == WALLY_OK);
|
|
|
|
return weight;
|
2016-04-24 12:23:35 +02:00
|
|
|
}
|
|
|
|
|
2020-05-26 05:39:25 +02:00
|
|
|
void wally_txid(const struct wally_tx *wtx, struct bitcoin_txid *txid)
|
2015-06-02 05:29:13 +02:00
|
|
|
{
|
2020-05-26 05:39:25 +02:00
|
|
|
u8 *arr;
|
|
|
|
size_t len, written;
|
|
|
|
int res;
|
|
|
|
|
|
|
|
/* Never use BIP141 form for txid */
|
|
|
|
res = wally_tx_get_length(wtx, 0, &len);
|
|
|
|
assert(res == WALLY_OK);
|
|
|
|
arr = tal_arr(NULL, u8, len);
|
|
|
|
res = wally_tx_to_bytes(wtx, 0, arr, len, &written);
|
|
|
|
assert(len == written);
|
2015-06-02 05:29:13 +02:00
|
|
|
|
2020-05-26 05:39:25 +02:00
|
|
|
sha256_double(&txid->shad, arr, len);
|
|
|
|
tal_free(arr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We used to have beautiful, optimal code which fed the tx parts directly
|
|
|
|
* into sha256_update(). But that was before libwally; but now we don't have
|
|
|
|
* to maintain our own transaction code, so there's that. */
|
|
|
|
void bitcoin_txid(const struct bitcoin_tx *tx, struct bitcoin_txid *txid)
|
|
|
|
{
|
|
|
|
wally_txid(tx->wtx, txid);
|
2015-06-02 05:29:13 +02:00
|
|
|
}
|
|
|
|
|
2019-03-01 13:23:22 +01:00
|
|
|
/* Use the bitcoin_tx destructor to also free the wally_tx */
|
|
|
|
static void bitcoin_tx_destroy(struct bitcoin_tx *tx)
|
|
|
|
{
|
|
|
|
wally_tx_free(tx->wtx);
|
|
|
|
}
|
|
|
|
|
2019-07-30 16:14:43 +02:00
|
|
|
struct bitcoin_tx *bitcoin_tx(const tal_t *ctx,
|
|
|
|
const struct chainparams *chainparams,
|
2020-01-29 12:59:06 +01:00
|
|
|
varint_t input_count, varint_t output_count,
|
|
|
|
u32 nlocktime)
|
2015-05-29 04:03:18 +02:00
|
|
|
{
|
|
|
|
struct bitcoin_tx *tx = tal(ctx, struct bitcoin_tx);
|
2019-07-30 22:04:55 +02:00
|
|
|
assert(chainparams);
|
2019-07-30 16:14:43 +02:00
|
|
|
|
2019-05-06 15:24:53 +02:00
|
|
|
/* If we are constructing an elements transaction we need to
|
|
|
|
* explicitly add the fee as an extra output. So allocate one more
|
|
|
|
* than the outputs we need internally. */
|
2019-09-25 22:38:45 +02:00
|
|
|
if (chainparams->is_elements)
|
2019-05-06 15:24:53 +02:00
|
|
|
output_count += 1;
|
|
|
|
|
2019-03-01 13:23:22 +01:00
|
|
|
wally_tx_init_alloc(WALLY_TX_VERSION_2, 0, input_count, output_count,
|
|
|
|
&tx->wtx);
|
|
|
|
tal_add_destructor(tx, bitcoin_tx_destroy);
|
|
|
|
|
2020-01-29 12:59:06 +01:00
|
|
|
tx->wtx->locktime = nlocktime;
|
2019-03-05 14:28:29 +01:00
|
|
|
tx->wtx->version = 2;
|
2019-07-30 16:14:43 +02:00
|
|
|
tx->chainparams = chainparams;
|
2020-05-21 03:57:01 +02:00
|
|
|
tx->psbt = new_psbt(tx, tx->wtx);
|
2020-05-21 03:57:00 +02:00
|
|
|
|
2015-05-29 04:03:18 +02:00
|
|
|
return tx;
|
|
|
|
}
|
2015-06-04 06:18:11 +02:00
|
|
|
|
2020-02-08 21:26:55 +01:00
|
|
|
void bitcoin_tx_finalize(struct bitcoin_tx *tx)
|
|
|
|
{
|
|
|
|
elements_tx_add_fee_output(tx);
|
|
|
|
assert(bitcoin_tx_check(tx));
|
|
|
|
}
|
|
|
|
|
2020-05-22 05:18:33 +02:00
|
|
|
struct bitcoin_tx *bitcoin_tx_with_psbt(const tal_t *ctx, struct wally_psbt *psbt STEALS)
|
|
|
|
{
|
|
|
|
struct bitcoin_tx *tx = bitcoin_tx(ctx, chainparams,
|
|
|
|
psbt->tx->num_inputs,
|
|
|
|
psbt->tx->num_outputs,
|
|
|
|
psbt->tx->locktime);
|
|
|
|
wally_tx_free(tx->wtx);
|
2020-06-06 21:47:40 +02:00
|
|
|
tx->wtx = psbt_finalize(psbt, false);
|
|
|
|
if (!tx->wtx && wally_tx_clone(psbt->tx, &tx->wtx) != WALLY_OK)
|
2020-05-29 19:13:47 +02:00
|
|
|
return NULL;
|
2020-05-22 05:18:33 +02:00
|
|
|
|
|
|
|
tal_free(tx->psbt);
|
|
|
|
tx->psbt = tal_steal(tx, psbt);
|
2020-06-06 21:47:40 +02:00
|
|
|
|
2020-05-22 05:18:33 +02:00
|
|
|
return tx;
|
|
|
|
}
|
|
|
|
|
2018-02-08 02:25:12 +01:00
|
|
|
struct bitcoin_tx *pull_bitcoin_tx(const tal_t *ctx, const u8 **cursor,
|
|
|
|
size_t *max)
|
2015-06-04 06:18:11 +02:00
|
|
|
{
|
2019-03-21 19:02:44 +01:00
|
|
|
size_t wsize;
|
2020-05-21 03:57:01 +02:00
|
|
|
int flags = WALLY_TX_FLAG_USE_WITNESS;
|
2018-02-08 02:25:12 +01:00
|
|
|
struct bitcoin_tx *tx = tal(ctx, struct bitcoin_tx);
|
2019-04-13 17:15:02 +02:00
|
|
|
|
2019-09-26 00:42:26 +02:00
|
|
|
if (chainparams->is_elements)
|
2019-04-13 17:15:02 +02:00
|
|
|
flags |= WALLY_TX_FLAG_USE_ELEMENTS;
|
|
|
|
|
|
|
|
if (wally_tx_from_bytes(*cursor, *max, flags, &tx->wtx) != WALLY_OK) {
|
2019-06-21 02:11:41 +02:00
|
|
|
fromwire_fail(cursor, max);
|
2019-03-01 13:23:22 +01:00
|
|
|
return tal_free(tx);
|
|
|
|
}
|
2019-04-13 17:15:02 +02:00
|
|
|
|
2019-03-01 13:23:22 +01:00
|
|
|
tal_add_destructor(tx, bitcoin_tx_destroy);
|
2019-04-13 17:15:02 +02:00
|
|
|
|
|
|
|
/* For whatever reason the length computation gets upset if we tell it
|
|
|
|
* that we are using elements. It wants to discover it on its own, NO
|
|
|
|
* CLUES! (Ms. Doyle)
|
|
|
|
*
|
|
|
|
* https://github.com/ElementsProject/libwally-core/issues/139
|
|
|
|
*/
|
|
|
|
wally_tx_get_length(tx->wtx, flags & ~WALLY_TX_FLAG_USE_ELEMENTS,
|
|
|
|
&wsize);
|
2019-03-25 13:52:31 +01:00
|
|
|
|
2019-10-04 12:27:48 +02:00
|
|
|
tx->chainparams = chainparams;
|
2015-06-04 06:18:11 +02:00
|
|
|
|
2020-05-21 03:57:01 +02:00
|
|
|
tx->psbt = new_psbt(tx, tx->wtx);
|
2020-05-21 03:57:00 +02:00
|
|
|
|
2019-03-25 13:52:31 +01:00
|
|
|
*cursor += wsize;
|
|
|
|
*max -= wsize;
|
2015-06-04 06:18:11 +02:00
|
|
|
return tx;
|
|
|
|
}
|
|
|
|
|
2016-01-21 21:11:47 +01:00
|
|
|
struct bitcoin_tx *bitcoin_tx_from_hex(const tal_t *ctx, const char *hex,
|
|
|
|
size_t hexlen)
|
2015-06-04 06:18:11 +02:00
|
|
|
{
|
2016-07-01 03:57:57 +02:00
|
|
|
const char *end;
|
2015-06-04 06:18:11 +02:00
|
|
|
u8 *linear_tx;
|
|
|
|
const u8 *p;
|
|
|
|
struct bitcoin_tx *tx;
|
|
|
|
size_t len;
|
|
|
|
|
2016-04-11 09:02:43 +02:00
|
|
|
end = memchr(hex, '\n', hexlen);
|
|
|
|
if (!end)
|
2016-07-01 03:57:57 +02:00
|
|
|
end = hex + hexlen;
|
2016-01-21 21:11:46 +01:00
|
|
|
|
2015-07-01 06:14:31 +02:00
|
|
|
len = hex_data_size(end - hex);
|
2016-01-21 21:11:46 +01:00
|
|
|
p = linear_tx = tal_arr(ctx, u8, len);
|
2015-07-01 06:14:31 +02:00
|
|
|
if (!hex_decode(hex, end - hex, linear_tx, len))
|
2016-01-21 21:11:46 +01:00
|
|
|
goto fail;
|
2015-06-04 06:18:11 +02:00
|
|
|
|
|
|
|
tx = pull_bitcoin_tx(ctx, &p, &len);
|
|
|
|
if (!tx)
|
2016-01-21 21:11:46 +01:00
|
|
|
goto fail;
|
2015-07-01 06:14:31 +02:00
|
|
|
|
2016-04-24 12:10:29 +02:00
|
|
|
if (len)
|
|
|
|
goto fail_free_tx;
|
2016-11-11 00:02:04 +01:00
|
|
|
|
2016-01-21 21:11:46 +01:00
|
|
|
tal_free(linear_tx);
|
2020-02-08 21:26:55 +01:00
|
|
|
|
2015-06-04 06:18:11 +02:00
|
|
|
return tx;
|
2016-01-21 21:11:46 +01:00
|
|
|
|
|
|
|
fail_free_tx:
|
|
|
|
tal_free(tx);
|
|
|
|
fail:
|
|
|
|
tal_free(linear_tx);
|
|
|
|
return NULL;
|
2015-06-04 06:18:11 +02:00
|
|
|
}
|
2015-06-05 05:05:46 +02:00
|
|
|
|
2017-12-18 07:41:52 +01:00
|
|
|
/* <sigh>. Bitcoind represents hashes as little-endian for RPC. */
|
2015-06-05 05:05:46 +02:00
|
|
|
static void reverse_bytes(u8 *arr, size_t len)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < len / 2; i++) {
|
|
|
|
unsigned char tmp = arr[i];
|
|
|
|
arr[i] = arr[len - 1 - i];
|
|
|
|
arr[len - 1 - i] = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool bitcoin_txid_from_hex(const char *hexstr, size_t hexstr_len,
|
2017-12-18 07:41:52 +01:00
|
|
|
struct bitcoin_txid *txid)
|
2015-06-05 05:05:46 +02:00
|
|
|
{
|
|
|
|
if (!hex_decode(hexstr, hexstr_len, txid, sizeof(*txid)))
|
|
|
|
return false;
|
2017-12-18 07:41:52 +01:00
|
|
|
reverse_bytes(txid->shad.sha.u.u8, sizeof(txid->shad.sha.u.u8));
|
2015-06-05 05:05:46 +02:00
|
|
|
return true;
|
|
|
|
}
|
2015-07-01 06:14:31 +02:00
|
|
|
|
2017-12-18 07:41:52 +01:00
|
|
|
bool bitcoin_txid_to_hex(const struct bitcoin_txid *txid,
|
2015-07-24 08:30:10 +02:00
|
|
|
char *hexstr, size_t hexstr_len)
|
|
|
|
{
|
2017-12-18 07:41:52 +01:00
|
|
|
struct sha256_double rev = txid->shad;
|
2015-07-24 08:30:10 +02:00
|
|
|
reverse_bytes(rev.sha.u.u8, sizeof(rev.sha.u.u8));
|
|
|
|
return hex_encode(&rev, sizeof(rev), hexstr, hexstr_len);
|
|
|
|
}
|
2017-01-04 04:37:15 +01:00
|
|
|
|
|
|
|
static char *fmt_bitcoin_tx(const tal_t *ctx, const struct bitcoin_tx *tx)
|
|
|
|
{
|
|
|
|
u8 *lin = linearize_tx(ctx, tx);
|
2017-01-10 05:49:25 +01:00
|
|
|
char *s = tal_hex(ctx, lin);
|
2017-01-04 04:37:15 +01:00
|
|
|
tal_free(lin);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2017-12-18 07:41:52 +01:00
|
|
|
static char *fmt_bitcoin_txid(const tal_t *ctx, const struct bitcoin_txid *txid)
|
|
|
|
{
|
|
|
|
char *hexstr = tal_arr(ctx, char, hex_str_size(sizeof(*txid)));
|
|
|
|
|
|
|
|
bitcoin_txid_to_hex(txid, hexstr, hex_str_size(sizeof(*txid)));
|
|
|
|
return hexstr;
|
|
|
|
}
|
|
|
|
|
2020-07-02 22:53:51 +02:00
|
|
|
static char *fmt_wally_tx(const tal_t *ctx, const struct wally_tx *tx)
|
|
|
|
{
|
|
|
|
u8 *lin = linearize_wtx(ctx, tx);
|
|
|
|
char *s = tal_hex(ctx, lin);
|
|
|
|
tal_free(lin);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2017-01-04 04:37:15 +01:00
|
|
|
REGISTER_TYPE_TO_STRING(bitcoin_tx, fmt_bitcoin_tx);
|
2017-12-18 07:41:52 +01:00
|
|
|
REGISTER_TYPE_TO_STRING(bitcoin_txid, fmt_bitcoin_txid);
|
2020-07-02 22:53:51 +02:00
|
|
|
REGISTER_TYPE_TO_STRING(wally_tx, fmt_wally_tx);
|
2020-05-15 12:30:43 +02:00
|
|
|
|
|
|
|
void fromwire_bitcoin_txid(const u8 **cursor, size_t *max,
|
|
|
|
struct bitcoin_txid *txid)
|
|
|
|
{
|
|
|
|
fromwire_sha256_double(cursor, max, &txid->shad);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct bitcoin_tx *fromwire_bitcoin_tx(const tal_t *ctx,
|
|
|
|
const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
struct bitcoin_tx *tx;
|
|
|
|
|
|
|
|
tx = pull_bitcoin_tx(ctx, cursor, max);
|
2020-05-19 03:28:13 +02:00
|
|
|
if (!tx)
|
|
|
|
return fromwire_fail(cursor, max);
|
|
|
|
|
2020-05-21 05:57:41 +02:00
|
|
|
/* pull_bitcoin_tx sets the psbt */
|
|
|
|
tal_free(tx->psbt);
|
2020-06-06 21:50:23 +02:00
|
|
|
tx->psbt = fromwire_wally_psbt(tx, cursor, max);
|
2020-05-21 05:57:41 +02:00
|
|
|
|
2020-05-15 12:30:43 +02:00
|
|
|
return tx;
|
|
|
|
}
|
|
|
|
|
|
|
|
void towire_bitcoin_txid(u8 **pptr, const struct bitcoin_txid *txid)
|
|
|
|
{
|
|
|
|
towire_sha256_double(pptr, &txid->shad);
|
|
|
|
}
|
|
|
|
|
|
|
|
void towire_bitcoin_tx(u8 **pptr, const struct bitcoin_tx *tx)
|
|
|
|
{
|
|
|
|
u8 *lin = linearize_tx(tmpctx, tx);
|
|
|
|
towire_u8_array(pptr, lin, tal_count(lin));
|
|
|
|
|
2020-06-06 21:50:23 +02:00
|
|
|
towire_wally_psbt(pptr, tx->psbt);
|
2020-05-15 12:30:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
struct bitcoin_tx_output *fromwire_bitcoin_tx_output(const tal_t *ctx,
|
|
|
|
const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
struct bitcoin_tx_output *output = tal(ctx, struct bitcoin_tx_output);
|
|
|
|
output->amount = fromwire_amount_sat(cursor, max);
|
|
|
|
u16 script_len = fromwire_u16(cursor, max);
|
|
|
|
output->script = fromwire_tal_arrn(output, cursor, max, script_len);
|
|
|
|
if (!*cursor)
|
|
|
|
return tal_free(output);
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
void towire_bitcoin_tx_output(u8 **pptr, const struct bitcoin_tx_output *output)
|
|
|
|
{
|
|
|
|
towire_amount_sat(pptr, output->amount);
|
|
|
|
towire_u16(pptr, tal_count(output->script));
|
|
|
|
towire_u8_array(pptr, output->script, tal_count(output->script));
|
|
|
|
}
|
2020-05-26 05:39:25 +02:00
|
|
|
|
|
|
|
bool wally_tx_input_spends(const struct wally_tx_input *input,
|
|
|
|
const struct bitcoin_txid *txid,
|
|
|
|
int outnum)
|
|
|
|
{
|
|
|
|
/* Useful, as tx_part can have some NULL inputs */
|
|
|
|
if (!input)
|
|
|
|
return false;
|
|
|
|
BUILD_ASSERT(sizeof(*txid) == sizeof(input->txhash));
|
|
|
|
if (memcmp(txid, input->txhash, sizeof(*txid)) != 0)
|
|
|
|
return false;
|
|
|
|
return input->index == outnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME(cdecker) Make the caller pass in a reference to amount_asset, and
|
|
|
|
* return false if unintelligible/encrypted. (WARN UNUSED). */
|
|
|
|
struct amount_asset
|
|
|
|
wally_tx_output_get_amount(const struct wally_tx_output *output)
|
|
|
|
{
|
|
|
|
struct amount_asset amount;
|
|
|
|
be64 raw;
|
|
|
|
|
|
|
|
if (chainparams->is_elements) {
|
|
|
|
assert(output->asset_len == sizeof(amount.asset));
|
|
|
|
memcpy(&amount.asset, output->asset, sizeof(amount.asset));
|
|
|
|
|
|
|
|
/* We currently only support explicit value asset tags, others
|
|
|
|
* are confidential, so don't even try to assign a value to
|
|
|
|
* it. */
|
|
|
|
if (output->asset[0] == 0x01) {
|
|
|
|
memcpy(&raw, output->value + 1, sizeof(raw));
|
|
|
|
amount.value = be64_to_cpu(raw);
|
|
|
|
} else {
|
|
|
|
amount.value = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Do not assign amount.asset, we should never touch it in
|
|
|
|
* non-elements scenarios. */
|
|
|
|
amount.value = output->satoshi;
|
|
|
|
}
|
|
|
|
|
|
|
|
return amount;
|
|
|
|
}
|
2020-07-06 07:26:14 +02:00
|
|
|
|
|
|
|
/* Various weights of transaction parts. */
|
|
|
|
size_t bitcoin_tx_core_weight(size_t num_inputs, size_t num_outputs)
|
|
|
|
{
|
|
|
|
size_t weight;
|
|
|
|
|
|
|
|
/* version, input count, output count, locktime */
|
|
|
|
weight = (4 + varint_size(num_inputs) + varint_size(num_outputs) + 4)
|
|
|
|
* 4;
|
|
|
|
|
|
|
|
/* Add segwit fields: marker + flag */
|
|
|
|
weight += 1 + 1;
|
|
|
|
|
|
|
|
/* A couple of things need to change for elements: */
|
|
|
|
if (chainparams->is_elements) {
|
|
|
|
/* Each transaction has surjection and rangeproof (both empty
|
|
|
|
* for us as long as we use unblinded L-BTC transactions). */
|
|
|
|
weight += 2 * 4;
|
|
|
|
|
|
|
|
/* An elements transaction has 1 additional output for fees */
|
|
|
|
weight += bitcoin_tx_output_weight(0);
|
|
|
|
}
|
|
|
|
return weight;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t bitcoin_tx_output_weight(size_t outscript_len)
|
|
|
|
{
|
|
|
|
size_t weight;
|
|
|
|
|
|
|
|
/* amount, len, scriptpubkey */
|
|
|
|
weight = (8 + varint_size(outscript_len) + outscript_len) * 4;
|
|
|
|
|
|
|
|
if (chainparams->is_elements) {
|
|
|
|
/* Each output additionally has an asset_tag (1 + 32), value
|
|
|
|
* is prefixed by a version (1 byte), an empty nonce (1
|
|
|
|
* byte), two empty proofs (2 bytes). */
|
|
|
|
weight += (32 + 1 + 1 + 1) * 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
return weight;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We grind signatures to get them down to 71 bytes (+1 for sighash flags) */
|
|
|
|
size_t bitcoin_tx_input_sig_weight(void)
|
|
|
|
{
|
|
|
|
return 1 + 71 + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We only do segwit inputs, and we assume witness is sig + key */
|
|
|
|
size_t bitcoin_tx_simple_input_weight(bool p2sh)
|
|
|
|
{
|
|
|
|
size_t weight;
|
|
|
|
|
|
|
|
/* Input weight: txid + index + sequence */
|
|
|
|
weight = (32 + 4 + 4) * 4;
|
|
|
|
|
|
|
|
/* We always encode the length of the script, even if empty */
|
|
|
|
weight += 1 * 4;
|
|
|
|
|
|
|
|
/* P2SH variants include push of <0 <20-byte-key-hash>> */
|
|
|
|
if (p2sh)
|
|
|
|
weight += 23 * 4;
|
|
|
|
|
|
|
|
/* Account for witness (1 byte count + sig + key) */
|
|
|
|
weight += 1 + (bitcoin_tx_input_sig_weight() + 1 + 33);
|
|
|
|
|
|
|
|
/* Elements inputs have 6 bytes of blank proofs attached. */
|
|
|
|
if (chainparams->is_elements)
|
|
|
|
weight += 6;
|
|
|
|
|
|
|
|
return weight;
|
|
|
|
}
|
2020-07-07 22:50:26 +02:00
|
|
|
|
|
|
|
struct amount_sat change_amount(struct amount_sat excess, u32 feerate_perkw)
|
|
|
|
{
|
|
|
|
size_t outweight;
|
|
|
|
|
|
|
|
/* Must be able to pay for its own additional weight */
|
|
|
|
outweight = bitcoin_tx_output_weight(BITCOIN_SCRIPTPUBKEY_P2WPKH_LEN);
|
|
|
|
if (!amount_sat_sub(&excess,
|
|
|
|
excess, amount_tx_fee(feerate_perkw, outweight)))
|
|
|
|
return AMOUNT_SAT(0);
|
|
|
|
|
|
|
|
/* Must be non-dust */
|
|
|
|
if (!amount_sat_greater_eq(excess, chainparams->dust_limit))
|
|
|
|
return AMOUNT_SAT(0);
|
|
|
|
|
|
|
|
return excess;
|
|
|
|
}
|