mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-06 05:49:30 +01:00
dffe2f516a
This is prep work for when we sign htlc txs with SIGHASH_SINGLE|SIGHASH_ANYONECANPAY. We still deal with raw signatures for the htlc txs at the moment, since we send them like that across the wire, and changing that was simply too painful (for the moment?). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1205 lines
34 KiB
C
1205 lines
34 KiB
C
#include <bitcoin/block.h>
|
|
#include <bitcoin/chainparams.h>
|
|
#include <bitcoin/privkey.h>
|
|
#include <bitcoin/script.h>
|
|
#include <ccan/array_size/array_size.h>
|
|
#include <ccan/breakpoint/breakpoint.h>
|
|
#include <ccan/cast/cast.h>
|
|
#include <ccan/fdpass/fdpass.h>
|
|
#include <ccan/tal/str/str.h>
|
|
#include <common/crypto_sync.h>
|
|
#include <common/derive_basepoints.h>
|
|
#include <common/funding_tx.h>
|
|
#include <common/gen_peer_status_wire.h>
|
|
#include <common/initial_channel.h>
|
|
#include <common/key_derive.h>
|
|
#include <common/memleak.h>
|
|
#include <common/peer_billboard.h>
|
|
#include <common/peer_failed.h>
|
|
#include <common/pseudorand.h>
|
|
#include <common/read_peer_msg.h>
|
|
#include <common/status.h>
|
|
#include <common/subdaemon.h>
|
|
#include <common/type_to_string.h>
|
|
#include <common/version.h>
|
|
#include <common/wire_error.h>
|
|
#include <errno.h>
|
|
#include <hsmd/gen_hsm_wire.h>
|
|
#include <inttypes.h>
|
|
#include <openingd/gen_opening_wire.h>
|
|
#include <poll.h>
|
|
#include <secp256k1.h>
|
|
#include <stdio.h>
|
|
#include <wally_bip32.h>
|
|
#include <wire/gen_peer_wire.h>
|
|
#include <wire/peer_wire.h>
|
|
#include <wire/wire.h>
|
|
#include <wire/wire_sync.h>
|
|
|
|
/* stdin == requests, 3 == peer, 4 == gossip */
|
|
#define REQ_FD STDIN_FILENO
|
|
#define PEER_FD 3
|
|
#define GOSSIP_FD 4
|
|
#define HSM_FD 5
|
|
|
|
struct state {
|
|
struct crypto_state cs;
|
|
struct pubkey next_per_commit[NUM_SIDES];
|
|
|
|
/* Constriants on a channel they open. */
|
|
u32 minimum_depth;
|
|
u32 min_feerate, max_feerate;
|
|
|
|
struct basepoints our_points;
|
|
struct pubkey our_funding_pubkey;
|
|
|
|
/* Initially temporary, then final channel id. */
|
|
struct channel_id channel_id;
|
|
|
|
/* Funding and feerate: set by opening peer. */
|
|
u64 funding_satoshis, push_msat;
|
|
u32 feerate_per_kw;
|
|
struct bitcoin_txid funding_txid;
|
|
u16 funding_txout;
|
|
|
|
struct channel_config localconf, remoteconf;
|
|
|
|
/* Limits on what remote config we accept */
|
|
u32 max_to_self_delay;
|
|
u64 min_effective_htlc_capacity_msat;
|
|
|
|
struct channel *channel;
|
|
|
|
bool can_accept_channel;
|
|
const struct chainparams *chainparams;
|
|
};
|
|
|
|
static void negotiation_aborted(struct state *state, bool am_funder,
|
|
const char *why)
|
|
{
|
|
status_debug("aborted opening negotiaion: %s", why);
|
|
peer_billboard(true, why);
|
|
|
|
/* If necessary, tell master that funding failed. */
|
|
if (am_funder) {
|
|
u8 *msg = towire_opening_funder_failed(NULL, why);
|
|
wire_sync_write(REQ_FD, take(msg));
|
|
}
|
|
|
|
/* Reset state. */
|
|
memset(&state->channel_id, 0, sizeof(state->channel_id));
|
|
state->channel = tal_free(state->channel);
|
|
}
|
|
|
|
/* For negotiation failures: we tell them it's their fault. */
|
|
static void negotiation_failed(struct state *state, bool am_funder,
|
|
const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
const char *errmsg;
|
|
u8 *msg;
|
|
|
|
va_start(ap, fmt);
|
|
errmsg = tal_vfmt(tmpctx, fmt, ap);
|
|
va_end(ap);
|
|
|
|
msg = towire_errorfmt(NULL, &state->channel_id,
|
|
"You gave bad parameters: %s", errmsg);
|
|
sync_crypto_write(&state->cs, PEER_FD, take(msg));
|
|
|
|
negotiation_aborted(state, am_funder, errmsg);
|
|
}
|
|
|
|
static bool check_config_bounds(struct state *state,
|
|
const struct channel_config *remoteconf,
|
|
bool am_funder)
|
|
{
|
|
u64 capacity_msat;
|
|
u64 reserve_msat;
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiving node MUST fail the channel if:
|
|
*...
|
|
* - `to_self_delay` is unreasonably large.
|
|
*/
|
|
if (remoteconf->to_self_delay > state->max_to_self_delay) {
|
|
negotiation_failed(state, am_funder,
|
|
"to_self_delay %u larger than %u",
|
|
remoteconf->to_self_delay,
|
|
state->max_to_self_delay);
|
|
return false;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiving node MAY fail the channel if:
|
|
*...
|
|
* - `funding_satoshis` is too small.
|
|
* - it considers `htlc_minimum_msat` too large.
|
|
* - it considers `max_htlc_value_in_flight_msat` too small.
|
|
* - it considers `channel_reserve_satoshis` too large.
|
|
* - it considers `max_accepted_htlcs` too small.
|
|
*/
|
|
/* We accumulate this into an effective bandwidth minimum. */
|
|
|
|
/* Overflow check before capacity calc. */
|
|
if (remoteconf->channel_reserve_satoshis > state->funding_satoshis) {
|
|
negotiation_failed(state, am_funder,
|
|
"channel_reserve_satoshis %"PRIu64
|
|
" too large for funding_satoshis %"PRIu64,
|
|
remoteconf->channel_reserve_satoshis,
|
|
state->funding_satoshis);
|
|
return false;
|
|
}
|
|
|
|
/* Consider highest reserve. */
|
|
reserve_msat = remoteconf->channel_reserve_satoshis * 1000;
|
|
if (state->localconf.channel_reserve_satoshis * 1000 > reserve_msat)
|
|
reserve_msat = state->localconf.channel_reserve_satoshis * 1000;
|
|
|
|
capacity_msat = state->funding_satoshis * 1000 - reserve_msat;
|
|
|
|
if (remoteconf->max_htlc_value_in_flight_msat < capacity_msat)
|
|
capacity_msat = remoteconf->max_htlc_value_in_flight_msat;
|
|
|
|
if (remoteconf->htlc_minimum_msat * (u64)1000 > capacity_msat) {
|
|
negotiation_failed(state, am_funder,
|
|
"htlc_minimum_msat %"PRIu64
|
|
" too large for funding_satoshis %"PRIu64
|
|
" capacity_msat %"PRIu64,
|
|
remoteconf->htlc_minimum_msat,
|
|
state->funding_satoshis,
|
|
capacity_msat);
|
|
return false;
|
|
}
|
|
|
|
if (capacity_msat < state->min_effective_htlc_capacity_msat) {
|
|
negotiation_failed(state, am_funder,
|
|
"channel capacity with funding %"PRIu64" msat,"
|
|
" reserves %"PRIu64"/%"PRIu64" msat,"
|
|
" max_htlc_value_in_flight_msat %"PRIu64
|
|
" is %"PRIu64" msat, which is below %"PRIu64" msat",
|
|
state->funding_satoshis * 1000,
|
|
remoteconf->channel_reserve_satoshis * 1000,
|
|
state->localconf.channel_reserve_satoshis * 1000,
|
|
remoteconf->max_htlc_value_in_flight_msat,
|
|
capacity_msat,
|
|
state->min_effective_htlc_capacity_msat);
|
|
return false;
|
|
}
|
|
|
|
/* We don't worry about how many HTLCs they accept, as long as > 0! */
|
|
if (remoteconf->max_accepted_htlcs == 0) {
|
|
negotiation_failed(state, am_funder,
|
|
"max_accepted_htlcs %u invalid",
|
|
remoteconf->max_accepted_htlcs);
|
|
return false;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiving node MUST fail the channel if:
|
|
*...
|
|
* - `max_accepted_htlcs` is greater than 483.
|
|
*/
|
|
if (remoteconf->max_accepted_htlcs > 483) {
|
|
negotiation_failed(state, am_funder,
|
|
"max_accepted_htlcs %u too large",
|
|
remoteconf->max_accepted_htlcs);
|
|
return false;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiving node MUST fail the channel if:
|
|
*...
|
|
* - `dust_limit_satoshis` is greater than `channel_reserve_satoshis`.
|
|
*/
|
|
if (remoteconf->dust_limit_satoshis
|
|
> remoteconf->channel_reserve_satoshis) {
|
|
negotiation_failed(state, am_funder,
|
|
"dust_limit_satoshis %"PRIu64
|
|
" too large for channel_reserve_satoshis %"
|
|
PRIu64,
|
|
remoteconf->dust_limit_satoshis,
|
|
remoteconf->channel_reserve_satoshis);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* We always set channel_reserve_satoshis to 1%, rounded up. */
|
|
static void set_reserve(struct state *state)
|
|
{
|
|
state->localconf.channel_reserve_satoshis
|
|
= (state->funding_satoshis + 99) / 100;
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The sending node:
|
|
*...
|
|
* - MUST set `channel_reserve_satoshis` greater than or equal to
|
|
* `dust_limit_satoshis`.
|
|
*/
|
|
if (state->localconf.channel_reserve_satoshis
|
|
< state->localconf.dust_limit_satoshis)
|
|
state->localconf.channel_reserve_satoshis
|
|
= state->localconf.dust_limit_satoshis;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The sending node:
|
|
*...
|
|
* - MUST ensure `temporary_channel_id` is unique from any other channel ID
|
|
* with the same peer.
|
|
*/
|
|
static void temporary_channel_id(struct channel_id *channel_id)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < sizeof(*channel_id); i++)
|
|
channel_id->id[i] = pseudorand(256);
|
|
}
|
|
|
|
/* Handle random messages we might get during opening negotiation,
|
|
* returning the first non-handled one, or NULL if we aborted negotiation. */
|
|
static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state,
|
|
bool am_funder)
|
|
{
|
|
for (;;) {
|
|
u8 *msg;
|
|
bool from_gossipd;
|
|
char *err;
|
|
bool all_channels;
|
|
struct channel_id actual;
|
|
|
|
clean_tmpctx();
|
|
msg = peer_or_gossip_sync_read(ctx, PEER_FD, GOSSIP_FD,
|
|
&state->cs, &from_gossipd);
|
|
if (from_gossipd) {
|
|
handle_gossip_msg(PEER_FD, &state->cs, take(msg));
|
|
continue;
|
|
}
|
|
|
|
if (is_msg_for_gossipd(msg)) {
|
|
wire_sync_write(GOSSIP_FD, take(msg));
|
|
continue;
|
|
}
|
|
|
|
if (is_peer_error(tmpctx, msg, &state->channel_id,
|
|
&err, &all_channels)) {
|
|
/* BOLT #1:
|
|
*
|
|
* - if no existing channel is referred to by the
|
|
* message:
|
|
* - MUST ignore the message.
|
|
*/
|
|
if (!err) {
|
|
tal_free(msg);
|
|
continue;
|
|
}
|
|
if (am_funder) {
|
|
msg = towire_opening_funder_failed(NULL, err);
|
|
wire_sync_write(REQ_FD, take(msg));
|
|
}
|
|
/* Close connection on all_channels error. */
|
|
if (all_channels)
|
|
peer_failed_received_errmsg(PEER_FD, GOSSIP_FD,
|
|
&state->cs, err,
|
|
NULL);
|
|
negotiation_aborted(state, am_funder,
|
|
tal_fmt(tmpctx, "They sent error %s",
|
|
err));
|
|
/* Return NULL so caller knows to stop negotiating. */
|
|
return NULL;
|
|
}
|
|
|
|
if (is_wrong_channel(msg, &state->channel_id, &actual)) {
|
|
status_trace("Rejecting %s for unknown channel_id %s",
|
|
wire_type_name(fromwire_peektype(msg)),
|
|
type_to_string(tmpctx, struct channel_id,
|
|
&actual));
|
|
sync_crypto_write(&state->cs, PEER_FD,
|
|
take(towire_errorfmt(NULL, &actual,
|
|
"Multiple channels"
|
|
" unsupported")));
|
|
tal_free(msg);
|
|
continue;
|
|
}
|
|
|
|
return msg;
|
|
}
|
|
}
|
|
static u8 *funder_channel(struct state *state,
|
|
u64 change_satoshis, u32 change_keyindex,
|
|
u8 channel_flags,
|
|
struct utxo **utxos,
|
|
const struct ext_key *bip32_base)
|
|
{
|
|
struct channel_id id_in;
|
|
u8 *msg;
|
|
struct bitcoin_tx *tx;
|
|
struct basepoints theirs;
|
|
struct pubkey their_funding_pubkey;
|
|
struct pubkey *changekey;
|
|
struct bitcoin_signature sig;
|
|
u32 minimum_depth;
|
|
const u8 *wscript;
|
|
struct bitcoin_tx *funding;
|
|
|
|
set_reserve(state);
|
|
|
|
temporary_channel_id(&state->channel_id);
|
|
|
|
if (state->funding_satoshis > state->chainparams->max_funding_satoshi)
|
|
status_failed(STATUS_FAIL_MASTER_IO,
|
|
"funding_satoshis must be < %"PRIu64", not %"PRIu64,
|
|
state->chainparams->max_funding_satoshi,
|
|
state->funding_satoshis);
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The sending node:
|
|
*...
|
|
* - MUST set `push_msat` to equal or less than 1000 *
|
|
* `funding_satoshis`.
|
|
*/
|
|
if (state->push_msat > 1000 * state->funding_satoshis)
|
|
status_failed(STATUS_FAIL_MASTER_IO,
|
|
"push-msat must be < %"PRIu64,
|
|
1000 * state->funding_satoshis);
|
|
|
|
msg = towire_open_channel(state,
|
|
&state->chainparams->genesis_blockhash,
|
|
&state->channel_id,
|
|
state->funding_satoshis, state->push_msat,
|
|
state->localconf.dust_limit_satoshis,
|
|
state->localconf.max_htlc_value_in_flight_msat,
|
|
state->localconf.channel_reserve_satoshis,
|
|
state->localconf.htlc_minimum_msat,
|
|
state->feerate_per_kw,
|
|
state->localconf.to_self_delay,
|
|
state->localconf.max_accepted_htlcs,
|
|
&state->our_funding_pubkey,
|
|
&state->our_points.revocation,
|
|
&state->our_points.payment,
|
|
&state->our_points.delayed_payment,
|
|
&state->our_points.htlc,
|
|
&state->next_per_commit[LOCAL],
|
|
channel_flags);
|
|
sync_crypto_write(&state->cs, PEER_FD, msg);
|
|
|
|
peer_billboard(false,
|
|
"Funding channel: offered, now waiting for accept_channel");
|
|
msg = opening_negotiate_msg(tmpctx, state, true);
|
|
if (!msg)
|
|
return NULL;
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiving node MUST fail the channel if:
|
|
*...
|
|
* - `funding_pubkey`, `revocation_basepoint`, `htlc_basepoint`,
|
|
* `payment_basepoint`, or `delayed_payment_basepoint` are not
|
|
* valid DER-encoded compressed secp256k1 pubkeys.
|
|
*/
|
|
if (!fromwire_accept_channel(msg, &id_in,
|
|
&state->remoteconf.dust_limit_satoshis,
|
|
&state->remoteconf
|
|
.max_htlc_value_in_flight_msat,
|
|
&state->remoteconf
|
|
.channel_reserve_satoshis,
|
|
&state->remoteconf.htlc_minimum_msat,
|
|
&minimum_depth,
|
|
&state->remoteconf.to_self_delay,
|
|
&state->remoteconf.max_accepted_htlcs,
|
|
&their_funding_pubkey,
|
|
&theirs.revocation,
|
|
&theirs.payment,
|
|
&theirs.delayed_payment,
|
|
&theirs.htlc,
|
|
&state->next_per_commit[REMOTE]))
|
|
peer_failed(&state->cs,
|
|
&state->channel_id,
|
|
"Parsing accept_channel %s", tal_hex(msg, msg));
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The `temporary_channel_id` MUST be the same as the
|
|
* `temporary_channel_id` in the `open_channel` message. */
|
|
if (!channel_id_eq(&id_in, &state->channel_id))
|
|
peer_failed(&state->cs,
|
|
&state->channel_id,
|
|
"accept_channel ids don't match: sent %s got %s",
|
|
type_to_string(msg, struct channel_id, &id_in),
|
|
type_to_string(msg, struct channel_id,
|
|
&state->channel_id));
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiver:
|
|
* - if `minimum_depth` is unreasonably large:
|
|
* - MAY reject the channel.
|
|
*/
|
|
if (minimum_depth > 10) {
|
|
negotiation_failed(state, true,
|
|
"minimum_depth %u larger than %u",
|
|
minimum_depth, 10);
|
|
return NULL;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiver:
|
|
*...
|
|
* - if `channel_reserve_satoshis` is less than `dust_limit_satoshis`
|
|
* within the `open_channel` message:
|
|
* - MUST reject the channel.
|
|
*
|
|
* - if `channel_reserve_satoshis` from the `open_channel` message is
|
|
* less than `dust_limit_satoshis`:
|
|
* - MUST reject the channel.
|
|
*/
|
|
if (state->remoteconf.channel_reserve_satoshis
|
|
< state->localconf.dust_limit_satoshis) {
|
|
negotiation_failed(state, true,
|
|
"channel reserve %"PRIu64
|
|
" would be below our dust %"PRIu64,
|
|
state->remoteconf.channel_reserve_satoshis,
|
|
state->localconf.dust_limit_satoshis);
|
|
return NULL;
|
|
}
|
|
if (state->localconf.channel_reserve_satoshis
|
|
< state->remoteconf.dust_limit_satoshis) {
|
|
negotiation_failed(state, true,
|
|
"dust limit %"PRIu64
|
|
" would be above our reserve %"PRIu64,
|
|
state->remoteconf.dust_limit_satoshis,
|
|
state->localconf.channel_reserve_satoshis);
|
|
return NULL;
|
|
}
|
|
|
|
if (!check_config_bounds(state, &state->remoteconf, true))
|
|
return NULL;
|
|
|
|
/* Now, ask create funding transaction to pay those two addresses. */
|
|
if (change_satoshis) {
|
|
changekey = tal(tmpctx, struct pubkey);
|
|
if (!bip32_pubkey(bip32_base, changekey, change_keyindex))
|
|
status_failed(STATUS_FAIL_MASTER_IO,
|
|
"Bad change key %u", change_keyindex);
|
|
} else
|
|
changekey = NULL;
|
|
|
|
funding = funding_tx(state, &state->funding_txout,
|
|
cast_const2(const struct utxo **, utxos),
|
|
state->funding_satoshis,
|
|
&state->our_funding_pubkey,
|
|
&their_funding_pubkey,
|
|
change_satoshis, changekey,
|
|
bip32_base);
|
|
bitcoin_txid(funding, &state->funding_txid);
|
|
|
|
state->channel = new_initial_channel(state,
|
|
&state->chainparams->genesis_blockhash,
|
|
&state->funding_txid,
|
|
state->funding_txout,
|
|
state->funding_satoshis,
|
|
state->funding_satoshis * 1000
|
|
- state->push_msat,
|
|
state->feerate_per_kw,
|
|
&state->localconf,
|
|
&state->remoteconf,
|
|
&state->our_points, &theirs,
|
|
&state->our_funding_pubkey,
|
|
&their_funding_pubkey,
|
|
LOCAL);
|
|
if (!state->channel)
|
|
peer_failed(&state->cs,
|
|
&state->channel_id,
|
|
"could not create channel with given config");
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* ### The `funding_created` Message
|
|
*
|
|
* This message describes the outpoint which the funder has created
|
|
* for the initial commitment transactions. After receiving the
|
|
* peer's signature, via `funding_signed`, it will broadcast the funding
|
|
* transaction.
|
|
*/
|
|
tx = initial_channel_tx(state, &wscript, state->channel,
|
|
&state->next_per_commit[REMOTE], REMOTE);
|
|
if (!tx) {
|
|
negotiation_failed(state, true,
|
|
"Could not meet their fees and reserve");
|
|
return NULL;
|
|
}
|
|
|
|
msg = towire_hsm_sign_remote_commitment_tx(NULL,
|
|
tx,
|
|
&state->channel->funding_pubkey[REMOTE],
|
|
state->channel->funding_msat / 1000);
|
|
|
|
wire_sync_write(HSM_FD, take(msg));
|
|
msg = wire_sync_read(tmpctx, HSM_FD);
|
|
if (!fromwire_hsm_sign_tx_reply(msg, &sig))
|
|
status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s",
|
|
tal_hex(tmpctx, msg));
|
|
|
|
status_trace("signature %s on tx %s using key %s",
|
|
type_to_string(tmpctx, struct bitcoin_signature, &sig),
|
|
type_to_string(tmpctx, struct bitcoin_tx, tx),
|
|
type_to_string(tmpctx, struct pubkey,
|
|
&state->our_funding_pubkey));
|
|
|
|
msg = towire_funding_created(state, &state->channel_id,
|
|
&state->funding_txid,
|
|
state->funding_txout,
|
|
&sig.s);
|
|
sync_crypto_write(&state->cs, PEER_FD, msg);
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* ### The `funding_signed` Message
|
|
*
|
|
* This message gives the funder the signature it needs for the first
|
|
* commitment transaction, so it can broadcast the transaction knowing
|
|
* that funds can be redeemed, if need be.
|
|
*/
|
|
peer_billboard(false,
|
|
"Funding channel: create first tx, now waiting for their signature");
|
|
|
|
msg = opening_negotiate_msg(tmpctx, state, true);
|
|
if (!msg)
|
|
return NULL;
|
|
|
|
sig.sighash_type = SIGHASH_ALL;
|
|
if (!fromwire_funding_signed(msg, &id_in, &sig.s))
|
|
peer_failed(&state->cs,
|
|
&state->channel_id,
|
|
"Parsing funding_signed: %s", tal_hex(msg, msg));
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* This message introduces the `channel_id` to identify the channel.
|
|
* It's derived from the funding transaction by combining the
|
|
* `funding_txid` and the `funding_output_index`, using big-endian
|
|
* exclusive-OR (i.e. `funding_output_index` alters the last 2
|
|
* bytes).
|
|
*/
|
|
derive_channel_id(&state->channel_id,
|
|
&state->funding_txid, state->funding_txout);
|
|
|
|
if (!channel_id_eq(&id_in, &state->channel_id))
|
|
peer_failed(&state->cs, &id_in,
|
|
"funding_signed ids don't match: expected %s got %s",
|
|
type_to_string(msg, struct channel_id,
|
|
&state->channel_id),
|
|
type_to_string(msg, struct channel_id, &id_in));
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The recipient:
|
|
* - if `signature` is incorrect:
|
|
* - MUST fail the channel.
|
|
*/
|
|
tx = initial_channel_tx(state, &wscript, state->channel,
|
|
&state->next_per_commit[LOCAL], LOCAL);
|
|
if (!tx) {
|
|
negotiation_failed(state, true,
|
|
"Could not meet our fees and reserve");
|
|
return NULL;
|
|
}
|
|
|
|
if (!check_tx_sig(tx, 0, NULL, wscript, &their_funding_pubkey, &sig)) {
|
|
peer_failed(&state->cs,
|
|
&state->channel_id,
|
|
"Bad signature %s on tx %s using key %s",
|
|
type_to_string(tmpctx, struct bitcoin_signature,
|
|
&sig),
|
|
type_to_string(tmpctx, struct bitcoin_tx, tx),
|
|
type_to_string(tmpctx, struct pubkey,
|
|
&their_funding_pubkey));
|
|
}
|
|
|
|
peer_billboard(false, "Funding channel: opening negotiation succeeded");
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The recipient:
|
|
*...
|
|
* - on receipt of a valid `funding_signed`:
|
|
* - SHOULD broadcast the funding transaction.
|
|
*/
|
|
return towire_opening_funder_reply(state,
|
|
&state->remoteconf,
|
|
tx,
|
|
&sig,
|
|
&state->cs,
|
|
&theirs.revocation,
|
|
&theirs.payment,
|
|
&theirs.htlc,
|
|
&theirs.delayed_payment,
|
|
&state->next_per_commit[REMOTE],
|
|
minimum_depth,
|
|
&their_funding_pubkey,
|
|
&state->funding_txid,
|
|
state->feerate_per_kw,
|
|
state->localconf.channel_reserve_satoshis);
|
|
}
|
|
|
|
static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg)
|
|
{
|
|
struct channel_id id_in;
|
|
struct basepoints theirs;
|
|
struct pubkey their_funding_pubkey;
|
|
struct bitcoin_signature theirsig, sig;
|
|
struct bitcoin_tx *local_commit, *remote_commit;
|
|
struct bitcoin_blkid chain_hash;
|
|
u8 *msg;
|
|
const u8 *wscript;
|
|
u8 channel_flags;
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiving node MUST fail the channel if:
|
|
*...
|
|
* - `funding_pubkey`, `revocation_basepoint`, `htlc_basepoint`,
|
|
* `payment_basepoint`, or `delayed_payment_basepoint` are not valid
|
|
* DER-encoded compressed secp256k1 pubkeys.
|
|
*/
|
|
if (!fromwire_open_channel(open_channel_msg, &chain_hash,
|
|
&state->channel_id,
|
|
&state->funding_satoshis, &state->push_msat,
|
|
&state->remoteconf.dust_limit_satoshis,
|
|
&state->remoteconf.max_htlc_value_in_flight_msat,
|
|
&state->remoteconf.channel_reserve_satoshis,
|
|
&state->remoteconf.htlc_minimum_msat,
|
|
&state->feerate_per_kw,
|
|
&state->remoteconf.to_self_delay,
|
|
&state->remoteconf.max_accepted_htlcs,
|
|
&their_funding_pubkey,
|
|
&theirs.revocation,
|
|
&theirs.payment,
|
|
&theirs.delayed_payment,
|
|
&theirs.htlc,
|
|
&state->next_per_commit[REMOTE],
|
|
&channel_flags))
|
|
peer_failed(&state->cs, NULL,
|
|
"Bad open_channel %s",
|
|
tal_hex(open_channel_msg, open_channel_msg));
|
|
|
|
/* We can't handle talking about more than one channel at once. */
|
|
if (!state->can_accept_channel) {
|
|
u8 *errmsg;
|
|
errmsg = towire_errorfmt(NULL, &state->channel_id,
|
|
"Already have active channel");
|
|
|
|
sync_crypto_write(&state->cs, PEER_FD, take(errmsg));
|
|
return NULL;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiving node MUST fail the channel if:
|
|
* - the `chain_hash` value is set to a hash of a chain
|
|
* that is unknown to the receiver.
|
|
*/
|
|
if (!bitcoin_blkid_eq(&chain_hash,
|
|
&state->chainparams->genesis_blockhash)) {
|
|
negotiation_failed(state, false,
|
|
"Unknown chain-hash %s",
|
|
type_to_string(tmpctx,
|
|
struct bitcoin_blkid,
|
|
&chain_hash));
|
|
return NULL;
|
|
}
|
|
|
|
/* BOLT #2 FIXME:
|
|
*
|
|
* The receiving node ... MUST fail the channel if `funding-satoshis`
|
|
* is greater than or equal to 2^24 */
|
|
if (state->funding_satoshis > state->chainparams->max_funding_satoshi) {
|
|
negotiation_failed(state, false,
|
|
"funding_satoshis %"PRIu64" too large",
|
|
state->funding_satoshis);
|
|
return NULL;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiving node MUST fail the channel if:
|
|
* ...
|
|
* - `push_msat` is greater than `funding_satoshis` * 1000.
|
|
*/
|
|
if (state->push_msat > state->funding_satoshis * 1000) {
|
|
peer_failed(&state->cs,
|
|
&state->channel_id,
|
|
"Our push_msat %"PRIu64
|
|
" would be too large for funding_satoshis %"PRIu64,
|
|
state->push_msat, state->funding_satoshis);
|
|
return NULL;
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The receiving node MUST fail the channel if:
|
|
*...
|
|
* - it considers `feerate_per_kw` too small for timely processing or
|
|
* unreasonably large.
|
|
*/
|
|
if (state->feerate_per_kw < state->min_feerate) {
|
|
negotiation_failed(state, false,
|
|
"feerate_per_kw %u below minimum %u",
|
|
state->feerate_per_kw, state->min_feerate);
|
|
return NULL;
|
|
}
|
|
|
|
if (state->feerate_per_kw > state->max_feerate) {
|
|
negotiation_failed(state, false,
|
|
"feerate_per_kw %u above maximum %u",
|
|
state->feerate_per_kw, state->max_feerate);
|
|
return NULL;
|
|
}
|
|
|
|
set_reserve(state);
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The sender:
|
|
*...
|
|
* - MUST set `channel_reserve_satoshis` greater than or equal to
|
|
* `dust_limit_satoshis` from the `open_channel` message.
|
|
* - MUST set `dust_limit_satoshis` less than or equal to
|
|
* `channel_reserve_satoshis` from the `open_channel` message.
|
|
*/
|
|
if (state->localconf.channel_reserve_satoshis
|
|
< state->remoteconf.dust_limit_satoshis) {
|
|
negotiation_failed(state, false,
|
|
"Our channel reserve %"PRIu64
|
|
" would be below their dust %"PRIu64,
|
|
state->localconf.channel_reserve_satoshis,
|
|
state->remoteconf.dust_limit_satoshis);
|
|
return NULL;
|
|
}
|
|
if (state->localconf.dust_limit_satoshis
|
|
> state->remoteconf.channel_reserve_satoshis) {
|
|
negotiation_failed(state, false,
|
|
"Our dust limit %"PRIu64
|
|
" would be above their reserve %"PRIu64,
|
|
state->localconf.dust_limit_satoshis,
|
|
state->remoteconf.channel_reserve_satoshis);
|
|
return NULL;
|
|
}
|
|
|
|
if (!check_config_bounds(state, &state->remoteconf, false))
|
|
return NULL;
|
|
|
|
msg = towire_accept_channel(state, &state->channel_id,
|
|
state->localconf.dust_limit_satoshis,
|
|
state->localconf
|
|
.max_htlc_value_in_flight_msat,
|
|
state->localconf.channel_reserve_satoshis,
|
|
state->localconf.htlc_minimum_msat,
|
|
state->minimum_depth,
|
|
state->localconf.to_self_delay,
|
|
state->localconf.max_accepted_htlcs,
|
|
&state->our_funding_pubkey,
|
|
&state->our_points.revocation,
|
|
&state->our_points.payment,
|
|
&state->our_points.delayed_payment,
|
|
&state->our_points.htlc,
|
|
&state->next_per_commit[LOCAL]);
|
|
|
|
sync_crypto_write(&state->cs, PEER_FD, take(msg));
|
|
|
|
peer_billboard(false,
|
|
"Incoming channel: accepted, now waiting for them to create funding tx");
|
|
|
|
msg = opening_negotiate_msg(tmpctx, state, false);
|
|
if (!msg)
|
|
return NULL;
|
|
|
|
theirsig.sighash_type = SIGHASH_ALL;
|
|
if (!fromwire_funding_created(msg, &id_in,
|
|
&state->funding_txid,
|
|
&state->funding_txout,
|
|
&theirsig.s))
|
|
peer_failed(&state->cs,
|
|
&state->channel_id,
|
|
"Parsing funding_created");
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The `temporary_channel_id` MUST be the same as the
|
|
* `temporary_channel_id` in the `open_channel` message.
|
|
*/
|
|
if (!channel_id_eq(&id_in, &state->channel_id))
|
|
peer_failed(&state->cs, &id_in,
|
|
"funding_created ids don't match: sent %s got %s",
|
|
type_to_string(msg, struct channel_id,
|
|
&state->channel_id),
|
|
type_to_string(msg, struct channel_id, &id_in));
|
|
|
|
state->channel = new_initial_channel(state,
|
|
&chain_hash,
|
|
&state->funding_txid,
|
|
state->funding_txout,
|
|
state->funding_satoshis,
|
|
state->push_msat,
|
|
state->feerate_per_kw,
|
|
&state->localconf,
|
|
&state->remoteconf,
|
|
&state->our_points, &theirs,
|
|
&state->our_funding_pubkey,
|
|
&their_funding_pubkey,
|
|
REMOTE);
|
|
if (!state->channel)
|
|
peer_failed(&state->cs,
|
|
&state->channel_id,
|
|
"We could not create channel with given config");
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* The recipient:
|
|
* - if `signature` is incorrect:
|
|
* - MUST fail the channel.
|
|
*/
|
|
local_commit = initial_channel_tx(state, &wscript, state->channel,
|
|
&state->next_per_commit[LOCAL], LOCAL);
|
|
if (!local_commit) {
|
|
negotiation_failed(state, false,
|
|
"Could not meet our fees and reserve");
|
|
return NULL;
|
|
}
|
|
|
|
if (!check_tx_sig(local_commit, 0, NULL, wscript, &their_funding_pubkey,
|
|
&theirsig)) {
|
|
peer_failed(&state->cs,
|
|
&state->channel_id,
|
|
"Bad signature %s on tx %s using key %s",
|
|
type_to_string(tmpctx, struct bitcoin_signature,
|
|
&theirsig),
|
|
type_to_string(tmpctx, struct bitcoin_tx, local_commit),
|
|
type_to_string(tmpctx, struct pubkey,
|
|
&their_funding_pubkey));
|
|
}
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* This message introduces the `channel_id` to identify the
|
|
* channel. It's derived from the funding transaction by combining the
|
|
* `funding_txid` and the `funding_output_index`, using big-endian
|
|
* exclusive-OR (i.e. `funding_output_index` alters the last 2 bytes).
|
|
*/
|
|
derive_channel_id(&state->channel_id,
|
|
&state->funding_txid, state->funding_txout);
|
|
|
|
/* BOLT #2:
|
|
*
|
|
* ### The `funding_signed` Message
|
|
*
|
|
* This message gives the funder the signature it needs for the first
|
|
* commitment transaction, so it can broadcast the transaction knowing
|
|
* that funds can be redeemed, if need be.
|
|
*/
|
|
remote_commit = initial_channel_tx(state, &wscript, state->channel,
|
|
&state->next_per_commit[REMOTE],
|
|
REMOTE);
|
|
if (!remote_commit) {
|
|
negotiation_failed(state, false,
|
|
"Could not meet their fees and reserve");
|
|
return NULL;
|
|
}
|
|
|
|
/* FIXME: Perhaps we should have channeld generate this, so we
|
|
* can't possibly send before channel committed? */
|
|
msg = towire_hsm_sign_remote_commitment_tx(NULL,
|
|
remote_commit,
|
|
&state->channel->funding_pubkey[REMOTE],
|
|
state->channel->funding_msat / 1000);
|
|
|
|
wire_sync_write(HSM_FD, take(msg));
|
|
msg = wire_sync_read(tmpctx, HSM_FD);
|
|
if (!fromwire_hsm_sign_tx_reply(msg, &sig))
|
|
status_failed(STATUS_FAIL_HSM_IO,
|
|
"Bad sign_tx_reply %s", tal_hex(tmpctx, msg));
|
|
|
|
/* We don't send this ourselves: channeld does, because master needs
|
|
* to save state to disk before doing so. */
|
|
assert(sig.sighash_type == SIGHASH_ALL);
|
|
msg = towire_funding_signed(state, &state->channel_id, &sig.s);
|
|
|
|
return towire_opening_fundee(state,
|
|
&state->remoteconf,
|
|
local_commit,
|
|
&theirsig,
|
|
&state->cs,
|
|
&theirs.revocation,
|
|
&theirs.payment,
|
|
&theirs.htlc,
|
|
&theirs.delayed_payment,
|
|
&state->next_per_commit[REMOTE],
|
|
&their_funding_pubkey,
|
|
&state->funding_txid,
|
|
state->funding_txout,
|
|
state->funding_satoshis,
|
|
state->push_msat,
|
|
channel_flags,
|
|
state->feerate_per_kw,
|
|
msg,
|
|
state->localconf.channel_reserve_satoshis);
|
|
}
|
|
|
|
static u8 *handle_peer_in(struct state *state)
|
|
{
|
|
u8 *msg = sync_crypto_read(tmpctx, &state->cs, PEER_FD);
|
|
enum wire_type t = fromwire_peektype(msg);
|
|
struct channel_id channel_id;
|
|
|
|
switch (t) {
|
|
case WIRE_OPEN_CHANNEL:
|
|
return fundee_channel(state, msg);
|
|
|
|
/* These are handled by handle_peer_gossip_or_error. */
|
|
case WIRE_PING:
|
|
case WIRE_PONG:
|
|
case WIRE_CHANNEL_ANNOUNCEMENT:
|
|
case WIRE_NODE_ANNOUNCEMENT:
|
|
case WIRE_CHANNEL_UPDATE:
|
|
case WIRE_QUERY_SHORT_CHANNEL_IDS:
|
|
case WIRE_REPLY_SHORT_CHANNEL_IDS_END:
|
|
case WIRE_QUERY_CHANNEL_RANGE:
|
|
case WIRE_REPLY_CHANNEL_RANGE:
|
|
case WIRE_GOSSIP_TIMESTAMP_FILTER:
|
|
case WIRE_ERROR:
|
|
case WIRE_CHANNEL_REESTABLISH:
|
|
/* These are all protocol violations at this stage. */
|
|
case WIRE_INIT:
|
|
case WIRE_ACCEPT_CHANNEL:
|
|
case WIRE_FUNDING_CREATED:
|
|
case WIRE_FUNDING_SIGNED:
|
|
case WIRE_FUNDING_LOCKED:
|
|
case WIRE_SHUTDOWN:
|
|
case WIRE_CLOSING_SIGNED:
|
|
case WIRE_UPDATE_ADD_HTLC:
|
|
case WIRE_UPDATE_FULFILL_HTLC:
|
|
case WIRE_UPDATE_FAIL_HTLC:
|
|
case WIRE_UPDATE_FAIL_MALFORMED_HTLC:
|
|
case WIRE_COMMITMENT_SIGNED:
|
|
case WIRE_REVOKE_AND_ACK:
|
|
case WIRE_UPDATE_FEE:
|
|
case WIRE_ANNOUNCEMENT_SIGNATURES:
|
|
/* Standard cases */
|
|
if (handle_peer_gossip_or_error(PEER_FD, GOSSIP_FD, &state->cs,
|
|
&state->channel_id, msg))
|
|
return NULL;
|
|
break;
|
|
}
|
|
|
|
sync_crypto_write(&state->cs, PEER_FD,
|
|
take(towire_errorfmt(NULL,
|
|
extract_channel_id(msg, &channel_id) ? &channel_id : NULL,
|
|
"Unexpected message %s: %s",
|
|
wire_type_name(t),
|
|
tal_hex(tmpctx, msg))));
|
|
|
|
/* FIXME: We don't actually want master to try to send an
|
|
* error, since peer is transient. This is a hack.
|
|
*/
|
|
status_broken("Unexpected message %s", wire_type_name(t));
|
|
peer_failed_connection_lost();
|
|
}
|
|
|
|
static void handle_gossip_in(struct state *state)
|
|
{
|
|
u8 *msg = wire_sync_read(NULL, GOSSIP_FD);
|
|
|
|
if (!msg)
|
|
status_failed(STATUS_FAIL_GOSSIP_IO,
|
|
"Reading gossip: %s", strerror(errno));
|
|
|
|
handle_gossip_msg(PEER_FD, &state->cs, take(msg));
|
|
}
|
|
|
|
static bool is_all_channel_error(const u8 *msg)
|
|
{
|
|
struct channel_id channel_id;
|
|
u8 *data;
|
|
|
|
if (!fromwire_error(msg, msg, &channel_id, &data))
|
|
return false;
|
|
tal_free(data);
|
|
return channel_id_is_all(&channel_id);
|
|
}
|
|
|
|
static void fail_if_all_error(const u8 *inner)
|
|
{
|
|
if (!is_all_channel_error(inner))
|
|
return;
|
|
|
|
status_info("Master said send err: %s",
|
|
sanitize_error(tmpctx, inner, NULL));
|
|
exit(0);
|
|
}
|
|
|
|
#if DEVELOPER
|
|
static void handle_dev_memleak(struct state *state, const u8 *msg)
|
|
{
|
|
struct htable *memtable;
|
|
bool found_leak;
|
|
|
|
memtable = memleak_enter_allocations(tmpctx, msg, msg);
|
|
|
|
/* Now delete state and things it has pointers to. */
|
|
memleak_remove_referenced(memtable, state);
|
|
|
|
found_leak = dump_memleak(memtable);
|
|
wire_sync_write(REQ_FD,
|
|
take(towire_opening_dev_memleak_reply(NULL,
|
|
found_leak)));
|
|
}
|
|
#endif /* DEVELOPER */
|
|
|
|
static u8 *handle_master_in(struct state *state)
|
|
{
|
|
u8 *msg = wire_sync_read(tmpctx, REQ_FD);
|
|
enum opening_wire_type t = fromwire_peektype(msg);
|
|
u64 change_satoshis;
|
|
u32 change_keyindex;
|
|
u8 channel_flags;
|
|
struct utxo **utxos;
|
|
struct ext_key bip32_base;
|
|
|
|
switch (t) {
|
|
case WIRE_OPENING_FUNDER:
|
|
if (!fromwire_opening_funder(state, msg,
|
|
&state->funding_satoshis,
|
|
&state->push_msat,
|
|
&state->feerate_per_kw,
|
|
&change_satoshis, &change_keyindex,
|
|
&channel_flags, &utxos,
|
|
&bip32_base))
|
|
master_badmsg(WIRE_OPENING_FUNDER, msg);
|
|
|
|
msg = funder_channel(state,
|
|
change_satoshis,
|
|
change_keyindex, channel_flags,
|
|
utxos, &bip32_base);
|
|
return msg;
|
|
|
|
case WIRE_OPENING_CAN_ACCEPT_CHANNEL:
|
|
if (!fromwire_opening_can_accept_channel(msg))
|
|
master_badmsg(WIRE_OPENING_CAN_ACCEPT_CHANNEL, msg);
|
|
state->can_accept_channel = true;
|
|
return NULL;
|
|
|
|
case WIRE_OPENING_DEV_MEMLEAK:
|
|
#if DEVELOPER
|
|
handle_dev_memleak(state, msg);
|
|
return NULL;
|
|
#endif
|
|
case WIRE_OPENING_DEV_MEMLEAK_REPLY:
|
|
case WIRE_OPENING_INIT:
|
|
case WIRE_OPENING_FUNDER_REPLY:
|
|
case WIRE_OPENING_FUNDEE:
|
|
case WIRE_OPENING_FUNDER_FAILED:
|
|
break;
|
|
}
|
|
|
|
status_failed(STATUS_FAIL_MASTER_IO,
|
|
"Unknown msg %s", tal_hex(tmpctx, msg));
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
setup_locale();
|
|
|
|
u8 *msg, *inner;
|
|
struct pollfd pollfd[3];
|
|
struct state *state = tal(NULL, struct state);
|
|
struct bitcoin_blkid chain_hash;
|
|
struct secret *none;
|
|
|
|
subdaemon_setup(argc, argv);
|
|
|
|
status_setup_sync(REQ_FD);
|
|
|
|
msg = wire_sync_read(tmpctx, REQ_FD);
|
|
if (!fromwire_opening_init(tmpctx, msg,
|
|
&chain_hash,
|
|
&state->localconf,
|
|
&state->max_to_self_delay,
|
|
&state->min_effective_htlc_capacity_msat,
|
|
&state->cs,
|
|
&state->our_points,
|
|
&state->our_funding_pubkey,
|
|
&state->minimum_depth,
|
|
&state->min_feerate, &state->max_feerate,
|
|
&state->can_accept_channel,
|
|
&inner))
|
|
master_badmsg(WIRE_OPENING_INIT, msg);
|
|
|
|
/* If they wanted to send an msg, do so before we waste time
|
|
* doing work. If it's a global error, we'll close
|
|
* immediately. */
|
|
if (inner != NULL) {
|
|
sync_crypto_write(&state->cs, PEER_FD, inner);
|
|
fail_if_all_error(inner);
|
|
}
|
|
|
|
state->chainparams = chainparams_by_chainhash(&chain_hash);
|
|
/* Initially we're not associated with a channel, but
|
|
* handle_peer_gossip_or_error wants this. */
|
|
memset(&state->channel_id, 0, sizeof(state->channel_id));
|
|
state->channel = NULL;
|
|
|
|
wire_sync_write(HSM_FD,
|
|
take(towire_hsm_get_per_commitment_point(NULL, 0)));
|
|
msg = wire_sync_read(tmpctx, HSM_FD);
|
|
if (!fromwire_hsm_get_per_commitment_point_reply(tmpctx, msg,
|
|
&state->next_per_commit[LOCAL],
|
|
&none))
|
|
status_failed(STATUS_FAIL_HSM_IO,
|
|
"Bad get_per_commitment_point_reply %s",
|
|
tal_hex(tmpctx, msg));
|
|
assert(none == NULL);
|
|
status_trace("Handed peer, entering loop");
|
|
|
|
pollfd[0].fd = REQ_FD;
|
|
pollfd[0].events = POLLIN;
|
|
pollfd[1].fd = GOSSIP_FD;
|
|
pollfd[1].events = POLLIN;
|
|
pollfd[2].fd = PEER_FD;
|
|
pollfd[2].events = POLLIN;
|
|
|
|
msg = NULL;
|
|
while (!msg) {
|
|
poll(pollfd, ARRAY_SIZE(pollfd), -1);
|
|
/* Subtle: handle_master_in can do its own poll loop, so
|
|
* don't try to service more than one fd per loop. */
|
|
if (pollfd[0].revents & POLLIN)
|
|
msg = handle_master_in(state);
|
|
else if (pollfd[2].revents & POLLIN)
|
|
msg = handle_peer_in(state);
|
|
else if (pollfd[1].revents & POLLIN)
|
|
handle_gossip_in(state);
|
|
|
|
clean_tmpctx();
|
|
}
|
|
|
|
/* Write message and hand back the fd. */
|
|
wire_sync_write(REQ_FD, msg);
|
|
fdpass_send(REQ_FD, PEER_FD);
|
|
fdpass_send(REQ_FD, GOSSIP_FD);
|
|
status_trace("Sent %s with fd",
|
|
opening_wire_type_name(fromwire_peektype(msg)));
|
|
tal_free(state);
|
|
daemon_shutdown();
|
|
return 0;
|
|
}
|