core-lightning/common/test/run-funding_tx.c
niftynei dc868630a8 tx-psbt: pass in the witness script (if known) when adding an input
Update the `bitcoin_tx_add_input` interface to accept a witness script
and or scriptPubkey.

We save the amount + witness script + witness program (if known) to
the PSBT object for a transaction when creating an input.
2020-06-11 13:13:13 +02:00

230 lines
9.0 KiB
C

#include <assert.h>
#include <bitcoin/address.h>
#include <bitcoin/base58.h>
#include <bitcoin/privkey.h>
#include <bitcoin/pubkey.h>
#include <ccan/str/hex/hex.h>
#include <common/setup.h>
#include <common/type_to_string.h>
#include <common/utils.h>
#include <inttypes.h>
#include <stdio.h>
#include "../amount.c"
#define SUPERVERBOSE printf
#include "../funding_tx.c"
#undef SUPERVERBOSE
#include "../key_derive.c"
#include "../type_to_string.c"
#include "../permute_tx.c"
#include "../utxo.c"
/* AUTOGENERATED MOCKS START */
/* Generated stub for fromwire */
const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED)
{ fprintf(stderr, "fromwire called!\n"); abort(); }
/* Generated stub for fromwire_bool */
bool fromwire_bool(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_bool called!\n"); abort(); }
/* Generated stub for fromwire_fail */
void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_fail called!\n"); abort(); }
/* Generated stub for fromwire_node_id */
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
/* Generated stub for fromwire_secp256k1_ecdsa_signature */
void fromwire_secp256k1_ecdsa_signature(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
secp256k1_ecdsa_signature *signature UNNEEDED)
{ fprintf(stderr, "fromwire_secp256k1_ecdsa_signature called!\n"); abort(); }
/* Generated stub for fromwire_sha256 */
void fromwire_sha256(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct sha256 *sha256 UNNEEDED)
{ fprintf(stderr, "fromwire_sha256 called!\n"); abort(); }
/* Generated stub for fromwire_tal_arrn */
u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED,
const u8 **cursor UNNEEDED, size_t *max UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_tal_arrn called!\n"); abort(); }
/* Generated stub for fromwire_u16 */
u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); }
/* Generated stub for fromwire_u32 */
u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u32 called!\n"); abort(); }
/* Generated stub for fromwire_u64 */
u64 fromwire_u64(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u64 called!\n"); abort(); }
/* Generated stub for fromwire_u8 */
u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); }
/* Generated stub for towire */
void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "towire called!\n"); abort(); }
/* Generated stub for towire_bool */
void towire_bool(u8 **pptr UNNEEDED, bool v UNNEEDED)
{ fprintf(stderr, "towire_bool called!\n"); abort(); }
/* Generated stub for towire_node_id */
void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED)
{ fprintf(stderr, "towire_node_id called!\n"); abort(); }
/* Generated stub for towire_secp256k1_ecdsa_signature */
void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED,
const secp256k1_ecdsa_signature *signature UNNEEDED)
{ fprintf(stderr, "towire_secp256k1_ecdsa_signature called!\n"); abort(); }
/* Generated stub for towire_sha256 */
void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED)
{ fprintf(stderr, "towire_sha256 called!\n"); abort(); }
/* Generated stub for towire_u16 */
void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
{ fprintf(stderr, "towire_u16 called!\n"); abort(); }
/* Generated stub for towire_u32 */
void towire_u32(u8 **pptr UNNEEDED, u32 v UNNEEDED)
{ fprintf(stderr, "towire_u32 called!\n"); abort(); }
/* Generated stub for towire_u64 */
void towire_u64(u8 **pptr UNNEEDED, u64 v UNNEEDED)
{ fprintf(stderr, "towire_u64 called!\n"); abort(); }
/* Generated stub for towire_u8 */
void towire_u8(u8 **pptr UNNEEDED, u8 v UNNEEDED)
{ fprintf(stderr, "towire_u8 called!\n"); abort(); }
/* Generated stub for towire_u8_array */
void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "towire_u8_array called!\n"); abort(); }
/* AUTOGENERATED MOCKS END */
#if 0
static struct sha256 sha256_from_hex(const char *hex)
{
struct sha256 sha256;
if (strstarts(hex, "0x"))
hex += 2;
if (!hex_decode(hex, strlen(hex), &sha256, sizeof(sha256)))
abort();
return sha256;
}
static struct privkey privkey_from_hex(const char *hex)
{
struct privkey pk;
size_t len;
if (strstarts(hex, "0x"))
hex += 2;
len = strlen(hex);
if (len == 66 && strends(hex, "01"))
len -= 2;
if (!hex_decode(hex, len, &pk, sizeof(pk)))
abort();
return pk;
}
#endif
int main(int argc, const char *argv[])
{
common_setup(argv[0]);
struct bitcoin_tx *input, *funding;
struct amount_sat fee, change;
struct pubkey local_funding_pubkey, remote_funding_pubkey;
struct privkey input_privkey;
struct pubkey inputkey;
bool testnet;
struct utxo utxo;
const struct utxo **utxomap;
struct amount_sat funding_sat;
u16 funding_outnum;
u8 *subscript, *script;
struct bitcoin_signature sig;
struct bitcoin_address addr;
struct amount_sat tmpamt;
struct amount_asset asset;
chainparams = chainparams_for_network("bitcoin");
/* BOLT #3:
*
* Block 1 coinbase transaction: 01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0100f2052a010000001976a9143ca33c2e4446f4a305f23c80df8ad1afdcf652f988ac00000000
*/
input = bitcoin_tx_from_hex(tmpctx,
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0100f2052a010000001976a9143ca33c2e4446f4a305f23c80df8ad1afdcf652f988ac00000000",
strlen("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0100f2052a010000001976a9143ca33c2e4446f4a305f23c80df8ad1afdcf652f988ac00000000"));
input->chainparams = chainparams_for_network("bitcoin");
assert(input);
/* BOLT #3:
* Block 1 coinbase privkey: 6bd078650fcee8444e4e09825227b801a1ca928debb750eb36e6d56124bb20e801
* # privkey in base58: cRCH7YNcarfvaiY1GWUKQrRGmoezvfAiqHtdRvxe16shzbd7LDMz
*/
if (!key_from_base58("cRCH7YNcarfvaiY1GWUKQrRGmoezvfAiqHtdRvxe16shzbd7LDMz", strlen("cRCH7YNcarfvaiY1GWUKQrRGmoezvfAiqHtdRvxe16shzbd7LDMz"),
&testnet, &input_privkey, &inputkey))
abort();
assert(testnet);
printf("* Block 1 coinbase privkey: %s\n",
type_to_string(tmpctx, struct privkey, &input_privkey));
/* BOLT #3:
*
* The funding transaction is paid to the following pubkeys:
*
* local_funding_pubkey: 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb
* remote_funding_pubkey: 030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1
*/
if (!pubkey_from_hexstr("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb",
strlen("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb"),
&local_funding_pubkey))
abort();
if (!pubkey_from_hexstr("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1",
strlen("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1"),
&remote_funding_pubkey))
abort();
bitcoin_txid(input, &utxo.txid);
utxo.outnum = 0;
utxo.amount = AMOUNT_SAT(5000000000);
utxo.is_p2sh = false;
utxo.close_info = NULL;
utxo.scriptPubkey = tal_hexdata(tmpctx, "a914a5996075e4b468c9fb01d131bf9d4052a6fee19e87", strlen("a914a5996075e4b468c9fb01d131bf9d4052a6fee19e87"));
funding_sat = AMOUNT_SAT(10000000);
fee = AMOUNT_SAT(13920);
printf("input[0] txid: %s\n",
tal_hexstr(tmpctx, &utxo.txid, sizeof(utxo.txid)));
printf("input[0] input: %u\n", utxo.outnum);
printf("input[0] satoshis: %s\n",
type_to_string(tmpctx, struct amount_sat, &utxo.amount));
printf("funding: %s\n",
type_to_string(tmpctx, struct amount_sat, &funding_sat));
utxomap = tal_arr(tmpctx, const struct utxo *, 1);
utxomap[0] = &utxo;
if (!amount_sat_sub(&change, utxo.amount, funding_sat)
|| !amount_sat_sub(&change, change, fee))
abort();
funding = funding_tx(tmpctx, chainparams,
&funding_outnum, utxomap,
funding_sat,
&local_funding_pubkey,
&remote_funding_pubkey,
change,
&inputkey, NULL);
printf("# fee: %s\n",
type_to_string(tmpctx, struct amount_sat, &fee));
asset = bitcoin_tx_output_get_amount(funding, !funding_outnum);
assert(amount_asset_is_main(&asset));
tmpamt = amount_asset_to_sat(&asset);
printf("change: %s\n",
type_to_string(tmpctx, struct amount_sat,
&tmpamt));
printf("funding output: %u\n", funding_outnum);
pubkey_to_hash160(&inputkey, &addr.addr);
subscript = scriptpubkey_p2pkh(funding, &addr);
sign_tx_input(funding, 0, subscript, NULL, &input_privkey, &inputkey,
SIGHASH_ALL, &sig);
script = bitcoin_redeem_p2pkh(funding, &inputkey, &sig);
bitcoin_tx_input_set_script(funding, 0, script);
printf("funding tx: %s\n",
tal_hex(tmpctx, linearize_tx(tmpctx, funding)));
/* No memory leaks please */
common_shutdown();
return 0;
}