Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ If you encrypt your `hsm_secret`, you will have to pass the `--encrypted-hsm` st

Developers wishing to contribute should start with the developer guide [here](doc/contribute-to-core-lightning/coding-style-guidelines.md).

### RGB Support

This is an experiemental branch that implement the RGB support in core lightning.

It is still a reseach project, so if you would like to help or look inside
the work that it is currently done, please run `git grep -n "TODO(bitfinix):"`

[blockstream-store-blog]: https://blockstream.com/2018/01/16/en-lightning-charge/
[std]: https://github.com/lightning/bolts
[prs]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat
Expand Down
17 changes: 17 additions & 0 deletions bitcoin/test/run-psbt-from-tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,23 @@ int main(int argc, char *argv[])
assert(final_scriptsig->value_len > 0);
assert(tx2->psbt->inputs[0].final_witness != NULL);

char *hex_tx = "0200000001882d49b841cb341defb60509f5863b163d32d1a819545761d31420cbf9db94d60000000000f8858a80024a01000000000000220020b6d8d2f575683f606ece57e33f59eaa146152f5c7163fb3e917b3cd19b6a558038073ba40b00000022002076f0b18b3c072222fd000432a309620dd43dfb776ab3fd710c9bda5efb0235f49c49c120";
tx = bitcoin_tx_from_hex(tmpctx, hex_tx, strlen(hex_tx));
psbt_input_get_amount(tx->psbt, 0);

msg = tal_arr(tmpctx, u8, 0);
/* convert to wire format */
towire_bitcoin_tx(&msg, tx);

len = tal_bytelen(msg);
assert(len > 0);

tx2 = fromwire_bitcoin_tx(tmpctx,
cast_const2(const u8 **, &msg), &len);
assert(tx2 != NULL);

psbt_input_get_amount(tx2->psbt, 0);

common_shutdown();
return 0;
}
6 changes: 6 additions & 0 deletions bitcoin/test/run-tx-encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <common/setup.h>
#include <common/utils.h>
#include <stdio.h>
#include <string.h>

/* AUTOGENERATED MOCKS START */
/* Generated stub for amount_asset_is_main */
Expand Down Expand Up @@ -125,6 +126,7 @@ int main(int argc, const char *argv[])
chainparams = chainparams_for_network("bitcoin");

struct bitcoin_tx *tx;
char *hex_tx;

tx = bitcoin_tx_from_hex(NULL, extended_tx, strlen(extended_tx));
assert(tx);
Expand Down Expand Up @@ -161,6 +163,10 @@ int main(int argc, const char *argv[])
"0204096eb817f7efb414ef4d3d8be39dd04374256d3b054a322d4a6ee22736d0"
"3b");

hex_tx = "020000000180e1806045e74fb8fe0356e6568fe723c2755e54563b2e8df2f7e99202c3d896000000000029635b80024a01000000000000220020ac0192675893119abba0193b6b52dc188d6d1032078903890e72a676ffa237df4294d5e829000000220020ad270f8b9c3719fafeaa3be48aebaeac2a953a1ef658f3d55e0d0439b51df508648d1a20";
tx = bitcoin_tx_from_hex(NULL, hex_tx, strlen(hex_tx));
assert(strcmp(hex_tx, fmt_bitcoin_tx(NULL, tx)) == 0);

tal_free(tx);
common_shutdown();
return 0;
Expand Down
1 change: 1 addition & 0 deletions bitcoin/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ static bool uses_witness(const struct wally_tx *wtx)
{
size_t i;

assert(wtx);
for (i = 0; i < wtx->num_inputs; i++) {
if (wtx->inputs[i].witness)
return true;
Expand Down
5 changes: 5 additions & 0 deletions common/bolt11.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ struct bolt11 {
u8 *metadata;

struct list_head extra_fields;

// FIXME(vincenzopalazzo): adds rgb information
//
// 1. `rgb_amt`
// 2. `rgb_contract_id`
};

/* Decodes and checks signature; returns NULL on error; description is
Expand Down
5 changes: 5 additions & 0 deletions common/bolt11_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,9 @@ void json_add_bolt11(struct json_stream *response,

json_add_string(response, "signature",
fmt_secp256k1_ecdsa_signature(tmpctx, &b11->sig));

// FIXME(vincenzopalazzo): adding tag RGB information
//
// 1. Adds `rgb_amt`
// 2. Adds `rgb_contract_id`
}
9 changes: 9 additions & 0 deletions common/json_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,15 @@ bool json_to_txid(const char *buffer, const jsmntok_t *tok,
tok->end - tok->start, txid);
}

bool json_to_tx(const char *buffer, const jsmntok_t *tok,
struct bitcoin_tx **tx)
{
*tx = bitcoin_tx_from_hex(buffer, buffer + tok->start,
tok->end - tok->start);
return *tx != NULL;
}


bool json_to_outpoint(const char *buffer, const jsmntok_t *tok,
struct bitcoin_outpoint *op)
{
Expand Down
5 changes: 5 additions & 0 deletions common/json_parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
/* Simple helpers are here: this file contains heavier ones */
#include <common/json_parse_simple.h>
#include <common/jsonrpc_errors.h>
#include <bitcoin/tx.h>

struct json_escape;
struct json_stream;
Expand Down Expand Up @@ -102,6 +103,10 @@ bool json_to_msat(const char *buffer, const jsmntok_t *tok,
bool json_to_txid(const char *buffer, const jsmntok_t *tok,
struct bitcoin_txid *txid);

/* Extract a bitcoin tx from this */
bool json_to_tx(const char *buffer, const jsmntok_t *tok,
struct bitcoin_tx **tx);

/* Extract a bitcoin outpoint from this */
bool json_to_outpoint(const char *buffer, const jsmntok_t *tok,
struct bitcoin_outpoint *op);
Expand Down
19 changes: 19 additions & 0 deletions common/test/run-json_scan.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include "config.h"
#include "../json_parse.c"
#include "../json_parse_simple.c"
#include <assert.h>
#include <common/amount.h>
#include <common/setup.h>
#include <stdio.h>
#include <string.h>
#include <wire/wire.h>

/* AUTOGENERATED MOCKS START */
Expand Down Expand Up @@ -244,5 +247,21 @@ int main(int argc, char *argv[])
assert(toks);
assert(toks->size == 4);

char *hex_tx = "020000000180e1806045e74fb8fe0356e6568fe723c2755e54563b2e8df2f7e99202c3d896000000000029635b80024a01000000000000220020ac0192675893119abba0193b6b52dc188d6d1032078903890e72a676ffa237df4294d5e829000000220020ad270f8b9c3719fafeaa3be48aebaeac2a953a1ef658f3d55e0d0439b51df508648d1a20";
buf = tal_fmt(tmpctx, "{\"tx\":\"%s\"}", hex_tx);
toks = json_parse_simple(tmpctx, buf, strlen(buf));
toks = json_get_member(buf, toks, "tx");
assert(toks->end - toks->start == strlen(hex_tx));

chainparams = chainparams_for_network("bitcoin");
struct bitcoin_tx *tx = bitcoin_tx_from_hex(NULL, hex_tx, strlen(hex_tx));
assert(tx);
assert(strcmp(hex_tx, fmt_bitcoin_tx(NULL, tx)) == 0);

tx = NULL;
assert(json_to_tx(buf, toks, &tx));
assert(tx);
assert(strcmp(hex_tx, fmt_bitcoin_tx(NULL, tx)) == 0);

common_shutdown();
}
5 changes: 5 additions & 0 deletions lightningd/invoice.c
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,11 @@ invoice_complete(struct invoice_info *info,
"preimage already used");
}

// FIXME(vincenzopalazzo): to support create rgb lightning invoice we should add:
//
// 1: `rgb_amount` tag that shows the rgb amount on the chain
// 2: `rgb_contract_id` tag that fix the invoice from a specific
// RGB assert.
if (!invoices_create(wallet->invoices,
&inv_dbid,
info->b11->msat,
Expand Down
99 changes: 97 additions & 2 deletions lightningd/opening_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ static void openchannel_hook_serialize(struct openchannel_hook_payload *payload,

/* openingd dies? Remove openingd ptr from payload */
static void openchannel_payload_remove_openingd(struct subd *openingd,
struct openchannel_hook_payload *payload)
struct openchannel_hook_payload *payload)
{
assert(payload->openingd == openingd);
payload->openingd = NULL;
Expand Down Expand Up @@ -860,6 +860,94 @@ static void opening_got_offer(struct subd *openingd,
plugin_hook_call_openchannel(openingd->ld, NULL, payload);
}

struct onfunding_channel_tx_hook_payload {
struct subd *openingd;
struct bitcoin_tx *tx;
struct channel_id *cid;
};

static void onfunding_channel_tx_hook_final(struct onfunding_channel_tx_hook_payload *payload STEALS)
{
struct subd *openingd = payload->openingd;
log_info(openingd->log, "from hook sending the tx %s", fmt_bitcoin_tx(tmpctx, payload->tx));
// FIXME(bitfinix): manage the errors!
subd_send_msg(openingd,
take(towire_openingd_on_funding_tx_reply(NULL, payload->tx)));
}

static void onfunding_channel_tx_hook_serialize(struct onfunding_channel_tx_hook_payload *payload,
struct json_stream *stream,
struct plugin *plugin)
{
struct bitcoin_txid txid;

bitcoin_txid(payload->tx, &txid);
json_object_start(stream, "onfunding_channel_tx");
json_add_tx(stream, "tx", payload->tx);
json_add_txid(stream, "txid", &txid);
json_add_psbt(stream, "psbt", payload->tx->psbt);
json_add_channel_id(stream, "channel_id", payload->cid);
json_object_end(stream);
}

static bool onfunding_channel_tx_hook_deserialize(struct onfunding_channel_tx_hook_payload *payload,
const char *buffer,
const jsmntok_t *toks)
{
const jsmntok_t *result_tok, *error_tok,
*tx_tok, *psbt_tok;

if ((error_tok = json_get_member(buffer, toks, "error")) != NULL)
fatal("Plugin returned an error inside the response to the"
" onfunding_channel_tx hook: %.*s",
toks[0].end - toks[0].start, buffer + toks[0].start);

if ((result_tok = json_get_member(buffer, toks, "result")) == NULL)
fatal("Plugin returned an invalid response (missing result) to the"
" onfunding_channel_tx hook: %.*s",
toks[0].end - toks[0].start, buffer + toks[0].start);

if ((tx_tok = json_get_member(buffer, result_tok, "tx")) == NULL)
fatal("Plugin returned an invalid response (missing tx) to the"
" onfunding_channel_tx hook: %.*s",
toks[0].end - toks[0].start, buffer + toks[0].start);

if ((psbt_tok = json_get_member(buffer, result_tok, "psbt")) == NULL)
fatal("Plugin returned an invalid response (missing psbt) to the"
" onfunding_channel_tx hook: %.*s",
toks[0].end - toks[0].start, buffer + toks[0].start);

if (!json_to_tx(buffer, tx_tok, &payload->tx))
fatal("Plugin returned an invalid (json to tx) response to the"
" onfunding_channel_tx hook: %.*s",
tx_tok[0].end - tx_tok[0].start, buffer + tx_tok[0].start);

payload->tx->psbt = json_to_psbt(buffer, buffer, psbt_tok);
return true;
}

REGISTER_PLUGIN_HOOK(onfunding_channel_tx,
onfunding_channel_tx_hook_deserialize,
onfunding_channel_tx_hook_final,
onfunding_channel_tx_hook_serialize,
struct onfunding_channel_tx_hook_payload *);


static char *opening_on_funding_tx(struct subd *openingd, const u8 *msg)
{
struct onfunding_channel_tx_hook_payload *payload;
payload = tal(openingd, struct onfunding_channel_tx_hook_payload);
payload->cid = tal(payload, struct channel_id);
payload->tx = tal(payload, struct bitcoin_tx);
payload->openingd = openingd;

if (!fromwire_openingd_on_funding_tx(msg, msg, &payload->tx, payload->cid))
return tal_fmt(tmpctx, "Unexpected encoding of openingd_on_funding_tx msg: %s",
tal_hex(tmpctx, msg));
plugin_hook_call_onfunding_channel_tx(openingd->ld, NULL, payload);
return NULL;
}

static unsigned int openingd_msg(struct subd *openingd,
const u8 *msg, const int *fds)
{
Expand Down Expand Up @@ -900,13 +988,20 @@ static unsigned int openingd_msg(struct subd *openingd,
case WIRE_OPENINGD_GOT_OFFER:
opening_got_offer(openingd, msg, uc);
return 0;

case WIRE_OPENINGD_ON_FUNDING_TX:
const char *err;
if ((err = opening_on_funding_tx(openingd, msg)) != NULL) {
log_debug(openingd->log, "Unexpected error while handling on funding tx: %s", err);
return 1;
}
return 0;
/* We send these! */
case WIRE_OPENINGD_INIT:
case WIRE_OPENINGD_FUNDER_START:
case WIRE_OPENINGD_FUNDER_COMPLETE:
case WIRE_OPENINGD_FUNDER_CANCEL:
case WIRE_OPENINGD_GOT_OFFER_REPLY:
case WIRE_OPENINGD_ON_FUNDING_TX_REPLY:
case WIRE_OPENINGD_DEV_MEMLEAK:
/* Replies never get here */
case WIRE_OPENINGD_DEV_MEMLEAK_REPLY:
Expand Down
14 changes: 14 additions & 0 deletions openingd/openingd.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* commit to the database once openingd succeeds.
*/
#include "config.h"
#include <assert.h>
#include <bitcoin/script.h>
#include <ccan/array_size/array_size.h>
#include <ccan/breakpoint/breakpoint.h>
Expand All @@ -31,6 +32,7 @@
#include <openingd/openingd_wiregen.h>
#include <wire/peer_wire.h>
#include <wire/wire_sync.h>
#include <wally_psbt.h>

/* stdin == lightningd, 3 == peer, 4 = hsmd */
#define REQ_FD STDIN_FILENO
Expand Down Expand Up @@ -703,6 +705,15 @@ static bool funder_finalize_channel_setup(struct state *state,
else
*pbase = NULL;

assert((*tx)->psbt->inputs[0].witness_utxo);
msg = towire_openingd_on_funding_tx(tmpctx, *tx, &cid);
wire_sync_write(REQ_FD, msg);
msg = wire_sync_read(tmpctx, REQ_FD);
if (!fromwire_openingd_on_funding_tx_reply(msg, msg, tx))
status_failed(STATUS_FAIL_MASTER_IO, "Bad onfunding_tx %s",
tal_hex(tmpctx, msg));

assert((*tx)->psbt->inputs[0].witness_utxo);
/* We ask the HSM to sign their commitment transaction for us: it knows
* our funding key, it just needs the remote funding key to create the
* witness script. It also needs the amount of the funding output,
Expand Down Expand Up @@ -815,6 +826,7 @@ static bool funder_finalize_channel_setup(struct state *state,
goto fail;
}

// TODO(bitfixnix): RGB for initial tx channel?
validate_initial_commitment_signature(HSM_FD, *tx, sig);

if (!check_tx_sig(*tx, 0, NULL, wscript, &state->their_funding_pubkey, sig)) {
Expand Down Expand Up @@ -1501,6 +1513,8 @@ static u8 *handle_master_in(struct state *state)
case WIRE_OPENINGD_FAILED:
case WIRE_OPENINGD_GOT_OFFER:
case WIRE_OPENINGD_GOT_OFFER_REPLY:
case WIRE_OPENINGD_ON_FUNDING_TX:
case WIRE_OPENINGD_ON_FUNDING_TX_REPLY:
break;
}

Expand Down
9 changes: 9 additions & 0 deletions openingd/openingd_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ msgdata,openingd_fundee,remote_shutdown_len,u16,
msgdata,openingd_fundee,remote_shutdown_scriptpubkey,u8,remote_shutdown_len
msgdata,openingd_fundee,channel_type,channel_type,

# Communicate the Funding Tx to master
msgtype,openingd_on_funding_tx,6045
msgdata,openingd_on_funding_tx,tx,bitcoin_tx,
msgdata,openingd_on_funding_tx,channel_id,channel_id,

# Get a reply from master -> openingd
msgtype,openingd_on_funding_tx_reply,6145
msgdata,openingd_on_funding_tx_reply,tx,bitcoin_tx,

# master -> openingd: do you have a memleak?
msgtype,openingd_dev_memleak,6033

Expand Down
3 changes: 3 additions & 0 deletions plugins/offers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,9 @@ static struct command_result *json_decode(struct command *cmd,

response = jsonrpc_stream_success(cmd);
json_add_string(response, "type", decodable->type);
// FIXME(vincenzopalazzo): To decode an RGB invoice we should
// make sure that the RGB is only supported in the bolt11,
// otherwise throws an error.
if (decodable->offer)
json_add_offer(response, decodable->offer);
if (decodable->invreq)
Expand Down
3 changes: 3 additions & 0 deletions plugins/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,8 @@ static struct command_result *json_pay(struct command *cmd,
/* FIXME: parameter should be invstring now */
p_req("bolt11", param_invstring, &b11str),
p_opt("amount_msat", param_msat, &msat),
// FIXME(vincenzopalazzo): adds the rgb_amount value that
// can be (maybe) optional inside the invoice.
p_opt("label", param_string, &label),
p_opt_def("riskfactor", param_millionths,
&riskfactor_millionths, 10000000),
Expand Down Expand Up @@ -1130,6 +1132,7 @@ static struct command_result *json_pay(struct command *cmd,
"Invalid bolt11:"
" sets feature var_onion with no secret");
} else {
// FIXME(vincenzopalazzo): fails if it is an bolt12 offer.
b12 = invoice_decode(tmpctx, b11str, strlen(b11str),
plugin_feature_set(cmd->plugin),
chainparams, &b12_fail);
Expand Down