|
|
|
#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/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_amount_sat */
|
|
|
|
struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
|
|
|
{ fprintf(stderr, "fromwire_amount_sat called!\n"); abort(); }
|
|
|
|
/* Generated stub for fromwire_bitcoin_txid */
|
|
|
|
void fromwire_bitcoin_txid(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
|
|
|
|
struct bitcoin_txid *txid UNNEEDED)
|
|
|
|
{ fprintf(stderr, "fromwire_bitcoin_txid 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 */
|
|
|
|
const 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_pubkey */
|
|
|
|
void fromwire_pubkey(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct pubkey *pubkey UNNEEDED)
|
|
|
|
{ fprintf(stderr, "fromwire_pubkey 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 towire_amount_sat */
|
|
|
|
void towire_amount_sat(u8 **pptr UNNEEDED, const struct amount_sat sat UNNEEDED)
|
|
|
|
{ fprintf(stderr, "towire_amount_sat called!\n"); abort(); }
|
|
|
|
/* Generated stub for towire_bitcoin_txid */
|
|
|
|
void towire_bitcoin_txid(u8 **pptr UNNEEDED, const struct bitcoin_txid *txid UNNEEDED)
|
|
|
|
{ fprintf(stderr, "towire_bitcoin_txid 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_pubkey */
|
|
|
|
void towire_pubkey(u8 **pptr UNNEEDED, const struct pubkey *pubkey UNNEEDED)
|
|
|
|
{ fprintf(stderr, "towire_pubkey 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_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(void)
|
|
|
|
{
|
|
|
|
setup_locale();
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
|
|
|
|
| SECP256K1_CONTEXT_SIGN);
|
|
|
|
setup_tmpctx();
|
|
|
|
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;
|
|
|
|
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 */
|
|
|
|
secp256k1_context_destroy(secp256k1_ctx);
|
|
|
|
tal_free(tmpctx);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|