Skip to content
Merged
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
1 change: 1 addition & 0 deletions common/jsonrpc_errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#define FUND_MAX_EXCEEDED 300
#define FUND_CANNOT_AFFORD 301
#define FUND_OUTPUT_IS_DUST 302
#define FUNDING_BROADCAST_FAIL 303

/* Errors from `invoice` command */
#define INVOICE_LABEL_ALREADY_EXISTS 900
Expand Down
15 changes: 13 additions & 2 deletions doc/lightning-fundchannel.7
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
.\" Title: lightning-fundchannel
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 12/07/2018
.\" Date: 01/22/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-FUNDCHANN" "7" "12/07/2018" "\ \&" "\ \&"
.TH "LIGHTNING\-FUNDCHANN" "7" "01/22/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Expand Down Expand Up @@ -95,6 +95,17 @@ The following error codes may occur:
302\&. The output amount is too small, and would be considered dust\&.
.RE
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
303\&. Broadcasting of the funding transaction failed, the internal call to bitcoin\-cli returned with an error\&.
.RE
.sp
Failure may also occur if \fBlightningd\fR and the peer cannot agree on channel parameters (funding limits, channel reserves, fees, etc\&.)\&.
.SH "SEE ALSO"
.sp
Expand Down
2 changes: 2 additions & 0 deletions doc/lightning-fundchannel.7.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ The following error codes may occur:
* 301. There are not enough funds in the internal wallet (including fees) to
create the transaction.
* 302. The output amount is too small, and would be considered dust.
* 303. Broadcasting of the funding transaction failed, the internal call to
bitcoin-cli returned with an error.

Failure may also occur if *lightningd* and the peer cannot agree on channel
parameters (funding limits, channel reserves, fees, etc.).
Expand Down
8 changes: 4 additions & 4 deletions lightningd/chaintopology.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ static void broadcast_done(struct bitcoind *bitcoind,
/* No longer needs to be disconnected if channel dies. */
tal_del_destructor2(otx->channel, clear_otx_channel, otx);

if (otx->failed && exitstatus != 0) {
otx->failed(otx->channel, exitstatus, msg);
if (otx->failed_or_success) {
otx->failed_or_success(otx->channel, exitstatus, msg);
tal_free(otx);
} else {
/* For continual rebroadcasting, until channel freed. */
Expand All @@ -213,7 +213,7 @@ static void broadcast_done(struct bitcoind *bitcoind,

void broadcast_tx(struct chain_topology *topo,
struct channel *channel, const struct bitcoin_tx *tx,
void (*failed)(struct channel *channel,
void (*failed_or_success)(struct channel *channel,
int exitstatus, const char *err))
{
/* Channel might vanish: topo owns it to start with. */
Expand All @@ -223,7 +223,7 @@ void broadcast_tx(struct chain_topology *topo,
otx->channel = channel;
bitcoin_txid(tx, &otx->txid);
otx->hextx = tal_hex(otx, rawtx);
otx->failed = failed;
otx->failed_or_success = failed_or_success;
tal_free(rawtx);
tal_add_destructor2(channel, clear_otx_channel, otx);

Expand Down
2 changes: 1 addition & 1 deletion lightningd/chaintopology.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct outgoing_tx {
struct channel *channel;
const char *hextx;
struct bitcoin_txid txid;
void (*failed)(struct channel *channel, int exitstatus, const char *err);
void (*failed_or_success)(struct channel *channel, int exitstatus, const char *err);
};

struct block {
Expand Down
84 changes: 58 additions & 26 deletions lightningd/opening_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,20 @@ struct uncommitted_channel {


struct funding_channel {
struct command *cmd; /* Which also owns us. */
struct command *cmd; /* Which initially owns us until openingd request */

struct wallet_tx wtx;
u64 push_msat;
u8 channel_flags;

/* Variables we need to compose fields in cmd's response */
u8 *linear;
struct channel_id cid;

/* Peer we're trying to reach. */
struct pubkey peerid;

/* Channel. */
/* Channel, subsequent owner of us */
struct uncommitted_channel *uc;
};

Expand Down Expand Up @@ -216,18 +221,56 @@ wallet_commit_channel(struct lightningd *ld,
}

static void funding_broadcast_failed(struct channel *channel,
int exitstatus, const char *err)
int exitstatus, const char *msg)
{
struct funding_channel *fc = channel->peer->uncommitted_channel->fc;
struct command *cmd = fc->cmd;

/* Massage output into shape so it doesn't kill the JSON serialization */
char *output = tal_strjoin(cmd, tal_strsplit(cmd, msg, "\n", STR_NO_EMPTY), " ", STR_NO_TRAIL);
was_pending(command_fail(cmd, FUNDING_BROADCAST_FAIL,
"Error broadcasting funding transaction: %s", output));
Comment thread
This conversation was marked as resolved.
Resolved

/* Frees fc too */
tal_free(fc->uc);

/* Keep in state CHANNELD_AWAITING_LOCKIN until (manual) broadcast */
}

static void funding_broadcast_success(struct channel *channel)
{
struct json_stream *response;
struct funding_channel *fc = channel->peer->uncommitted_channel->fc;
struct command *cmd = fc->cmd;

response = json_stream_success(cmd);
json_object_start(response, NULL);
json_add_hex_talarr(response, "tx", fc->linear);
json_add_txid(response, "txid", &channel->funding_txid);
json_add_string(response, "channel_id",
type_to_string(tmpctx, struct channel_id, &fc->cid));
json_object_end(response);
was_pending(command_success(cmd, response));

/* Frees fc too */
tal_free(fc->uc);
}

static void funding_broadcast_failed_or_success(struct channel *channel,
int exitstatus, const char *msg)
{
channel_internal_error(channel,
"Funding broadcast exited with %i: %s",
exitstatus, err);
if (exitstatus == 0) {
funding_broadcast_success(channel);
} else {
funding_broadcast_failed(channel, exitstatus, msg);
}
}

static void opening_funder_finished(struct subd *openingd, const u8 *resp,
const int *fds,
struct funding_channel *fc)
{
u8 *msg, *linear;
u8 *msg;
struct channel_info channel_info;
struct bitcoin_tx *fundingtx;
struct bitcoin_txid funding_txid, expected_txid;
Expand All @@ -239,9 +282,7 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp,
u32 feerate;
u64 change_satoshi;
struct channel *channel;
struct json_stream *response;
struct lightningd *ld = openingd->ld;
struct channel_id cid;

assert(tal_count(fds) == 2);

Expand Down Expand Up @@ -372,32 +413,23 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp,
if (tal_count(fundingtx->output) == 2)
txfilter_add_scriptpubkey(ld->owned_txfilter, fundingtx->output[!funding_outnum].script);

/* Send it out and watch for confirms. */
broadcast_tx(ld->topology, channel, fundingtx, funding_broadcast_failed);
/* We need these to compose cmd's response in funding_broadcast_success */
fc->linear = linearize_tx(fc->cmd, fundingtx);
derive_channel_id(&fc->cid, &channel->funding_txid, funding_outnum);

/* Send it out and watch for confirms. */
broadcast_tx(ld->topology, channel, fundingtx, funding_broadcast_failed_or_success);
channel_watch_funding(ld, channel);

/* Start normal channel daemon. */
peer_start_channeld(channel, &cs, fds[0], fds[1], NULL, false);

/* Mark consumed outputs as spent */
wallet_confirm_utxos(ld->wallet, fc->wtx.utxos);

response = json_stream_success(fc->cmd);
json_object_start(response, NULL);
linear = linearize_tx(response, fundingtx);
json_add_hex_talarr(response, "tx", linear);
json_add_txid(response, "txid", &channel->funding_txid);
derive_channel_id(&cid, &channel->funding_txid, funding_outnum);
json_add_string(response, "channel_id",
type_to_string(tmpctx, struct channel_id, &cid));
json_object_end(response);
was_pending(command_success(fc->cmd, response));
/* Start normal channel daemon. */
peer_start_channeld(channel, &cs, fds[0], fds[1], NULL, false);

subd_release_channel(openingd, fc->uc);
fc->uc->openingd = NULL;

/* Frees fc too, and tmpctx */
tal_free(fc->uc);
return;

failed:
Expand Down
1 change: 1 addition & 0 deletions tests/btcproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def _handle_request(self, r):
except JSONRPCError as e:
reply = {
"error": e.error,
"code": -32603,
"id": r['id']
}
self.request_count += 1
Expand Down
5 changes: 3 additions & 2 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1112,15 +1112,16 @@ def test_fundee_forget_funding_tx_unconfirmed(node_factory, bitcoind):
time.sleep(1)

def mock_sendrawtransaction(r):
return {'error': 'sendrawtransaction disabled'}
return {'id': r['id'], 'error': {'code': 100, 'message': 'sendrawtransaction disabled'}}

# Prevent funder from broadcasting funding tx (any tx really).
l1.daemon.rpcproxy.mock_rpc('sendrawtransaction', mock_sendrawtransaction)

# Fund the channel.
# The process will complete, but funder will be unable
# to broadcast and confirm funding tx.
l1.rpc.fundchannel(l2.info['id'], 10**6)
with pytest.raises(RpcError, match=r'sendrawtransaction disabled'):
l1.rpc.fundchannel(l2.info['id'], 10**6)

# Generate blocks until unconfirmed.
bitcoind.generate_block(blocks)
Expand Down