mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-05 21:44:42 +01:00
7283efa5b5
Currently the only source for amount_asset is the value getter on a tx output, and we don't hand it too far around (mainly ignoring it if it isn't the chain's main currency). Eventually we could bubble them up to the wallet, use them to select outputs or actually support assets in the channels. Since we don't hand them around too widely I thought it was ok for them to be pass-by-value rather than having to allocate them and pass them around by reference. They're just 41 bytes currently so the overhead should be ok. Signed-off-by: Christian Decker <@cdecker>
213 lines
7.9 KiB
C
213 lines
7.9 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/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_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_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(); }
|
|
/* 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;
|
|
}
|