doc: big BOLT update to incorporate warnings language.

We do this (send warnings) in almost all cases anyway, so mainly this
is a textual update, but there are some changes:

1. Send ERROR not WARNING if they send a malformed commitment secret.
2. Send WARNING not ERROR if they get the shutdown_scriptpubkey wrong (vs upfront)
3. Send WARNING not ERROR if they send a bad shutdown_scriptpubkey (e.g. p2pkh in future)
4. Rename some vars 'err' to 'warn' to make it clear we send a warning.

This means test_option_upfront_shutdown_script can be made reliable, too,
and it now warns and doesn't automatically close channel.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2022-03-31 19:40:50 +10:30
parent 9f06a59e3c
commit 2526e804f7
22 changed files with 191 additions and 144 deletions

View File

@@ -24,7 +24,7 @@ CCANDIR := ccan
# Where we keep the BOLT RFCs
BOLTDIR := ../lightning-rfc/
DEFAULT_BOLTVERSION := c876dac2b5038f6499154d0a739240b6ff5db70d
DEFAULT_BOLTVERSION := 93909f67f6a48ee3f155a6224c182e612dd5f187
# Can be overridden on cmdline.
BOLTVERSION := $(DEFAULT_BOLTVERSION)

View File

@@ -728,7 +728,8 @@ static void handle_peer_feechange(struct peer *peer, const u8 *msg)
* A receiving node:
*...
* - if the sender is not responsible for paying the Bitcoin fee:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (peer->channel->opener != REMOTE)
peer_failed_warn(peer->pps, &peer->channel_id,
@@ -742,7 +743,8 @@ static void handle_peer_feechange(struct peer *peer, const u8 *msg)
* A receiving node:
* - if the `update_fee` is too low for timely processing, OR is
* unreasonably large:
* - SHOULD fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (!feerate_same_or_better(peer->channel, feerate,
peer->feerate_min, peer->feerate_max))
@@ -757,7 +759,8 @@ static void handle_peer_feechange(struct peer *peer, const u8 *msg)
*
* - if the sender cannot afford the new fee rate on the receiving
* node's current commitment transaction:
* - SHOULD fail the channel,
* - SHOULD send a `warning` and close the connection, or send an
* `error` and fail the channel.
* - but MAY delay this check until the `update_fee` is committed.
*/
if (!channel_update_feerate(peer->channel, feerate))
@@ -1627,7 +1630,8 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg)
* - once all pending updates are applied:
* - if `signature` is not valid for its local commitment transaction
* OR non-compliant with LOW-S-standard rule...:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (!check_tx_sig(txs[0], 0, NULL, funding_wscript,
&peer->channel->funding_pubkey[REMOTE], &commit_sig)) {
@@ -1651,7 +1655,8 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg)
*...
* - if `num_htlcs` is not equal to the number of HTLC outputs in the
* local commitment transaction:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (tal_count(htlc_sigs) != tal_count(txs) - 1)
peer_failed_warn(peer->pps, &peer->channel_id,
@@ -1662,7 +1667,8 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg)
*
* - if any `htlc_signature` is not valid for the corresponding HTLC
* transaction OR non-compliant with LOW-S-standard rule...:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
for (i = 0; i < tal_count(htlc_sigs); i++) {
u8 *wscript;
@@ -1813,11 +1819,11 @@ static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg)
* A receiving node:
* - if `per_commitment_secret` is not a valid secret key or does not
* generate the previous `per_commitment_point`:
* - MUST fail the channel.
* - MUST send an `error` and fail the channel.
*/
memcpy(&privkey, &old_commit_secret, sizeof(privkey));
if (!pubkey_from_privkey(&privkey, &per_commit_point)) {
peer_failed_warn(peer->pps, &peer->channel_id,
peer_failed_err(peer->pps, &peer->channel_id,
"Bad privkey %s",
type_to_string(msg, struct privkey, &privkey));
}
@@ -1957,7 +1963,8 @@ static void handle_peer_fail_malformed_htlc(struct peer *peer, const u8 *msg)
*
* - if the `BADONION` bit in `failure_code` is not set for
* `update_fail_malformed_htlc`:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (!(failure_code & BADONION)) {
peer_failed_warn(peer->pps, &peer->channel_id,
@@ -2011,6 +2018,7 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown)
* feature, and the receiving node received a non-zero-length
* `shutdown_scriptpubkey` in `open_channel` or `accept_channel`, and
* that `shutdown_scriptpubkey` is not equal to `scriptpubkey`:
* - MAY send a `warning`.
* - MUST fail the connection.
*/
/* openingd only sets this if feature was negotiated at opening. */
@@ -2018,7 +2026,7 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown)
&& !memeq(scriptpubkey, tal_count(scriptpubkey),
peer->remote_upfront_shutdown_script,
tal_count(peer->remote_upfront_shutdown_script)))
peer_failed_err(peer->pps, &peer->channel_id,
peer_failed_warn(peer->pps, &peer->channel_id,
"scriptpubkey %s is not as agreed upfront (%s)",
tal_hex(peer, scriptpubkey),
tal_hex(peer, peer->remote_upfront_shutdown_script));
@@ -2528,12 +2536,12 @@ static void check_future_dataloss_fields(struct peer *peer,
* commitment transaction:
* ...
* - if `your_last_per_commitment_secret` does not match the expected values:
* - SHOULD fail the channel.
* - SHOULD send an `error` and fail the channel.
* - otherwise, if it supports `option_data_loss_protect`:
*...
* - otherwise (`your_last_per_commitment_secret` or
* `my_current_per_commitment_point` do not match the expected values):
* - SHOULD fail the channel.
* - SHOULD send an `error` and fail the channel.
*/
static void check_current_dataloss_fields(struct peer *peer,
u64 next_revocation_number,
@@ -2950,10 +2958,10 @@ skip_tlvs:
* - if `next_revocation_number` is not equal to 1 greater
* than the commitment number of the last `revoke_and_ack` the
* receiving node has sent:
* - SHOULD fail the channel.
* - SHOULD send an `error` and fail the channel.
* - if it has not sent `revoke_and_ack`, AND
* `next_revocation_number` is not equal to 0:
* - SHOULD fail the channel.
* - SHOULD send an `error` and fail the channel.
*/
if (next_revocation_number == peer->next_index[LOCAL] - 2) {
/* Don't try to retransmit revocation index -1! */
@@ -3021,7 +3029,7 @@ skip_tlvs:
* - if `next_commitment_number` is not 1 greater than the
* commitment number of the last `commitment_signed` message the
* receiving node has sent:
* - SHOULD fail the channel.
* - SHOULD send an `error` and fail the channel.
*/
} else if (next_commitment_number != peer->next_index[REMOTE])
peer_failed_err(peer->pps,

View File

@@ -559,7 +559,8 @@ static enum channel_add_err add_htlc(struct channel *channel,
*...
* - if sending node sets `cltv_expiry` to greater or equal to
* 500000000:
* - SHOULD fail the channel.
* - SHOULD send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (!blocks_to_abs_locktime(cltv_expiry, &htlc->expiry)) {
return CHANNEL_ERR_INVALID_EXPIRY;
@@ -584,7 +585,8 @@ static enum channel_add_err add_htlc(struct channel *channel,
* A receiving node:
* - receiving an `amount_msat` equal to 0, OR less than its own
* `htlc_minimum_msat`:
* - SHOULD fail the channel.
* - SHOULD send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (amount_msat_eq(htlc->amount, AMOUNT_MSAT(0))) {
return CHANNEL_ERR_HTLC_BELOW_MINIMUM;
@@ -652,7 +654,8 @@ static enum channel_add_err add_htlc(struct channel *channel,
* - if a sending node... adds more than receiver
* `max_htlc_value_in_flight_msat` worth of offered HTLCs to its
* local commitment transaction:
* - SHOULD fail the channel.
* - SHOULD send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
/* We don't enforce this for channel_force_htlcs: some might already
@@ -670,7 +673,8 @@ static enum channel_add_err add_htlc(struct channel *channel,
* - receiving an `amount_msat` that the sending node cannot afford at
* the current `feerate_per_kw` (while maintaining its channel
* reserve and any `to_local_anchor` and `to_remote_anchor` costs):
* - SHOULD fail the channel.
* - SHOULD send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (enforce_aggregate_limits) {
struct amount_msat remainder;
@@ -894,7 +898,8 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel,
*
* - if the `payment_preimage` value in `update_fulfill_htlc`
* doesn't SHA256 hash to the corresponding HTLC `payment_hash`:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (!sha256_eq(&hash, &htlc->rhash))
return CHANNEL_ERR_BAD_PREIMAGE;
@@ -905,7 +910,8 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel,
*
* - if the `id` does not correspond to an HTLC in its current
* commitment transaction:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (!htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) {
status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s",
@@ -957,7 +963,8 @@ enum channel_remove_err channel_fail_htlc(struct channel *channel,
* A receiving node:
* - if the `id` does not correspond to an HTLC in its current
* commitment transaction:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (!htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) {
status_unusual("channel_fail_htlc: %"PRIu64" in state %s",
@@ -1145,7 +1152,8 @@ static int change_htlcs(struct channel *channel,
*...
* - if the sender cannot afford the new fee rate on the receiving node's
* current commitment transaction:
* - SHOULD fail the channel,
* - SHOULD send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
u32 approx_max_feerate(const struct channel *channel)
{
@@ -1257,7 +1265,8 @@ bool can_opener_afford_feerate(const struct channel *channel, u32 feerate_per_kw
*
* - if the sender cannot afford the new fee rate on the receiving
* node's current commitment transaction:
* - SHOULD fail the channel
* - SHOULD send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
/* Note: sender == opener */

View File

@@ -291,7 +291,8 @@ receive_offer(struct per_peer_state *pps,
* - if the `signature` is not valid for either variant of closing transaction
* specified in [BOLT #3](03-transactions.md#closing-transaction)
* OR non-compliant with LOW-S-standard rule...:
* - MUST fail the connection.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
tx = close_tx(tmpctx, chainparams, pps, channel_id,
local_wallet_index,

View File

@@ -33,10 +33,12 @@ struct short_channel_id *decode_short_ids(const tal_t *ctx, const u8 *encoded)
* The receiver:
* - if the first byte of `encoded_short_ids` is not a known encoding
* type:
* - MAY fail the connection
* - MAY send a `warning`.
* - MAY close the connection.
* - if `encoded_short_ids` does not decode into a whole number of
* `short_channel_id`:
* - MAY fail the connection
* - MAY send a `warning`.
* - MAY close the connection.
*/
type = fromwire_u8(&encoded, &max);
switch (type) {
@@ -75,10 +77,12 @@ bigsize_t *decode_scid_query_flags(const tal_t *ctx,
*...
* - if the incoming message includes `query_short_channel_ids_tlvs`:
* - if `encoding_type` is not a known encoding type:
* - MAY fail the connection
* - MAY send a `warning`.
* - MAY close the connection.
* - if `encoded_query_flags` does not decode to exactly one flag per
* `short_channel_id`:
* - MAY fail the connection.
* - MAY send a `warning`.
* - MAY close the connection.
*/
switch (qf->encoding_type) {
case ARR_ZLIB:

View File

@@ -123,7 +123,8 @@ static const struct dependency feature_deps[] = {
* `option_anchor_outputs` | ... | ... | `option_static_remotekey`
*/
{ OPT_ANCHOR_OUTPUTS, OPT_STATIC_REMOTEKEY },
/* BOLT #9:
/* FIXME: This dep was added later! */
/* BOLT-master #9:
* Name | Description | Context | Dependencies |
*...
* `option_anchors_zero_fee_htlc_tx` | ... | ... | `option_static_remotekey`

View File

@@ -16,7 +16,6 @@ bool check_ping_make_pong(const tal_t *ctx, const u8 *ping, u8 **pong)
/* BOLT #1:
*
* A node receiving a `ping` message:
*...
* - if `num_pong_bytes` is less than 65532:
* - MUST respond by sending a `pong` message, with `byteslen` equal
* to `num_pong_bytes`.

View File

@@ -34,16 +34,23 @@ bool is_peer_error(const tal_t *ctx, const u8 *msg,
* ...
* The receiving node:
* - upon receiving `error`:
* - MUST fail the channel referred to by the error message, if that
* channel is with the sending node.
* - if no existing channel is referred to by the message:
* - if `channel_id` is all zero:
* - MUST fail all channels with the sending node.
* - otherwise:
* - MUST fail the channel referred to by `channel_id`, if that channel is with the sending node.
* - upon receiving `warning`:
* - SHOULD log the message for later diagnosis.
* - MAY disconnect.
* - MAY reconnect after some delay to retry.
* - MAY attempt `shutdown` if permitted at this point.
* - if no existing channel is referred to by `channel_id`:
* - MUST ignore the message.
*/
/* FIXME: The spec changed, so for *errors* all 0 is not special.
* But old gossipd would send these, so we turn them into warnings */
if (channel_id_is_all(&err_chanid))
*warning = true;
else if (!channel_id_eq(&err_chanid, channel_id))
/* FIXME: We don't actually free all channels at once, they'll
* have to error each in turn. */
if (!channel_id_is_all(&err_chanid)
&& !channel_id_eq(&err_chanid, channel_id))
*desc = tal_free(*desc);
return true;

View File

@@ -26,10 +26,7 @@ struct sockaddr_un;
*
* * `1`: ipv4; data = `[4:ipv4_addr][2:port]` (length 6)
* * `2`: ipv6; data = `[16:ipv6_addr][2:port]` (length 18)
* * `3`: Tor v2 onion service; data = `[10:onion_addr][2:port]` (length 12)
* * version 2 onion service addresses; Encodes an 80-bit, truncated `SHA-1` hash
* of a 1024-bit `RSA` public key for the onion service (a.k.a. Tor
* hidden service).
* * `3`: Deprecated (length 12). Used to contain Tor v2 onion services.
* * `4`: Tor v3 onion service; data = `[35:onion_addr][2:port]` (length 37)
* * version 3 ([prop224](https://gitweb.torproject.org/torspec.git/tree/proposals/224-rend-spec-ng.txt))
* onion service addresses; Encodes:

View File

@@ -364,7 +364,7 @@ struct io_plan *peer_connected(struct io_conn *conn,
* - upon receiving unknown _odd_ feature bits that are non-zero:
* - MUST ignore the bit.
* - upon receiving unknown _even_ feature bits that are non-zero:
* - MUST fail the connection.
* - MUST close the connection.
*/
unsup = features_unsupported(daemon->our_features, their_features,
INIT_FEATURE);

View File

@@ -1225,7 +1225,6 @@ void send_manual_ping(struct daemon *daemon, const u8 *msg)
/* BOLT #1:
*
* A node receiving a `ping` message:
*...
* - if `num_pong_bytes` is less than 65532:
* - MUST respond by sending a `pong` message, with `byteslen` equal
* to `num_pong_bytes`.

View File

@@ -75,7 +75,7 @@ static struct io_plan *peer_init_received(struct io_conn *conn,
* The receiving node:
* ...
* - upon receiving `networks` containing no common chains
* - MAY fail the connection.
* - MAY close the connection.
*/
if (tlvs->networks) {
if (!contains_common_chain(tlvs->networks)) {

View File

@@ -258,7 +258,8 @@ const u8 *handle_query_short_channel_ids(struct peer *peer, const u8 *msg)
* - if the incoming message includes
* `query_short_channel_ids_tlvs`:
* - if `encoding_type` is not a known encoding type:
* - MAY fail the connection
* - MAY send a `warning`.
* - MAY close the connection.
*/
flags = decode_scid_query_flags(tmpctx, tlvs->query_flags);
if (!flags) {
@@ -288,7 +289,8 @@ const u8 *handle_query_short_channel_ids(struct peer *peer, const u8 *msg)
* - if it has not sent `reply_short_channel_ids_end` to a
* previously received `query_short_channel_ids` from this
* sender:
* - MAY fail the connection.
* - MAY send a `warning`.
* - MAY close the connection.
*/
if (peer->scid_queries || peer->scid_query_nodes) {
return towire_warningfmt(peer, NULL,
@@ -308,7 +310,8 @@ const u8 *handle_query_short_channel_ids(struct peer *peer, const u8 *msg)
*...
* - if `encoded_query_flags` does not decode to exactly one flag per
* `short_channel_id`:
* - MAY fail the connection.
* - MAY send a `warning`.
* - MAY close the connection.
*/
if (!flags) {
/* Pretend they asked for everything. */

View File

@@ -886,7 +886,7 @@ u8 *handle_channel_announcement(struct routing_state *rstate,
{
struct pending_cannouncement *pending;
struct bitcoin_blkid chain_hash;
u8 *features, *err;
u8 *features, *warn;
secp256k1_ecdsa_signature node_signature_1, node_signature_2;
secp256k1_ecdsa_signature bitcoin_signature_1, bitcoin_signature_2;
struct chan *chan;
@@ -911,7 +911,7 @@ u8 *handle_channel_announcement(struct routing_state *rstate,
&pending->node_id_2,
&pending->bitcoin_key_1,
&pending->bitcoin_key_2)) {
err = towire_warningfmt(rstate, NULL,
warn = towire_warningfmt(rstate, NULL,
"Malformed channel_announcement %s",
tal_hex(pending, pending->announce));
goto malformed;
@@ -991,7 +991,7 @@ u8 *handle_channel_announcement(struct routing_state *rstate,
}
/* Note that if node_id_1 or node_id_2 are malformed, it's caught here */
err = check_channel_announcement(rstate,
warn = check_channel_announcement(rstate,
&pending->node_id_1,
&pending->node_id_2,
&pending->bitcoin_key_1,
@@ -1001,13 +1001,15 @@ u8 *handle_channel_announcement(struct routing_state *rstate,
&bitcoin_signature_1,
&bitcoin_signature_2,
pending->announce);
if (err) {
if (warn) {
/* BOLT #7:
*
* - if `bitcoin_signature_1`, `bitcoin_signature_2`,
* `node_signature_1` OR `node_signature_2` are invalid OR NOT
* correct:
* - SHOULD fail the connection.
* - SHOULD send a `warning`.
* - MAY close the connection.
* - MUST ignore the message.
*/
goto malformed;
}
@@ -1049,7 +1051,7 @@ u8 *handle_channel_announcement(struct routing_state *rstate,
malformed:
tal_free(pending);
*scid = NULL;
return err;
return warn;
ignored:
tal_free(pending);
@@ -1458,7 +1460,7 @@ u8 *handle_channel_update(struct routing_state *rstate, const u8 *update TAKES,
struct bitcoin_blkid chain_hash;
u8 direction;
struct pending_cannouncement *pending;
u8 *err;
u8 *warn;
serialized = tal_dup_talarr(tmpctx, u8, update);
if (!fromwire_channel_update(serialized, &signature,
@@ -1467,10 +1469,10 @@ u8 *handle_channel_update(struct routing_state *rstate, const u8 *update TAKES,
&channel_flags, &expiry,
&htlc_minimum, &fee_base_msat,
&fee_proportional_millionths)) {
err = towire_warningfmt(rstate, NULL,
warn = towire_warningfmt(rstate, NULL,
"Malformed channel_update %s",
tal_hex(tmpctx, serialized));
return err;
return warn;
}
direction = channel_flags & 0x1;
@@ -1523,18 +1525,18 @@ u8 *handle_channel_update(struct routing_state *rstate, const u8 *update TAKES,
return NULL;
}
err = check_channel_update(rstate, owner, &signature, serialized);
if (err) {
warn = check_channel_update(rstate, owner, &signature, serialized);
if (warn) {
/* BOLT #7:
*
* - if `signature` is not a valid signature, using `node_id`
* of the double-SHA256 of the entire message following the
* `signature` field (including unknown fields following
* `fee_proportional_millionths`):
* - SHOULD send a `warning` and close the connection.
* - MUST NOT process the message further.
* - SHOULD fail the connection.
*/
return err;
return warn;
}
routing_add_channel_update(rstate, take(serialized), 0, peer, force);
@@ -1712,13 +1714,14 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann,
/* BOLT #7:
*
* - if `node_id` is NOT a valid compressed public key:
* - SHOULD fail the connection.
* - SHOULD send a `warning`.
* - MAY close the connection.
* - MUST NOT process the message further.
*/
u8 *err = towire_warningfmt(rstate, NULL,
u8 *warn = towire_warningfmt(rstate, NULL,
"Malformed node_announcement %s",
tal_hex(tmpctx, node_ann));
return err;
return warn;
}
sha256_double(&hash, serialized + 66, tal_count(serialized) - 66);
@@ -1731,10 +1734,10 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann,
* message following the `signature` field
* (including unknown fields following
* `fee_proportional_millionths`):
* - SHOULD send a `warning` and close the connection.
* - MUST NOT process the message further.
* - SHOULD fail the connection.
*/
u8 *err = towire_warningfmt(rstate, NULL,
u8 *warn = towire_warningfmt(rstate, NULL,
"Bad signature for %s hash %s"
" on node_announcement %s",
type_to_string(tmpctx,
@@ -1744,7 +1747,7 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann,
struct sha256_double,
&hash),
tal_hex(tmpctx, node_ann));
return err;
return warn;
}
wireaddrs = fromwire_wireaddr_array(tmpctx, addresses);
@@ -1753,13 +1756,14 @@ u8 *handle_node_announcement(struct routing_state *rstate, const u8 *node_ann,
*
* - if `addrlen` is insufficient to hold the address
* descriptors of the known types:
* - SHOULD fail the connection.
* - SHOULD send a `warning`.
* - MAY close the connection.
*/
u8 *err = towire_warningfmt(rstate, NULL,
u8 *warn = towire_warningfmt(rstate, NULL,
"Malformed wireaddrs %s in %s.",
tal_hex(tmpctx, wireaddrs),
tal_hex(tmpctx, node_ann));
return err;
return warn;
}
/* May still fail, if we don't know the node. */

View File

@@ -9,6 +9,7 @@
#include <common/shutdown_scriptpubkey.h>
#include <common/type_to_string.h>
#include <common/wire_error.h>
#include <connectd/connectd_wiregen.h>
#include <errno.h>
#include <hsmd/capabilities.h>
#include <lightningd/chaintopology.h>
@@ -289,18 +290,32 @@ static void peer_got_shutdown(struct channel *channel, const u8 *msg)
return;
}
/* FIXME: Add to spec that we must allow repeated shutdown! */
tal_free(channel->shutdown_scriptpubkey[REMOTE]);
channel->shutdown_scriptpubkey[REMOTE] = scriptpubkey;
/* BOLT #2:
* A receiving node:
*...
* - if the `scriptpubkey` is not in one of the above forms:
* - SHOULD send a `warning`.
*/
if (!valid_shutdown_scriptpubkey(scriptpubkey, anysegwit, anchors)) {
channel_fail_permanent(channel,
REASON_PROTOCOL,
u8 *warning = towire_warningfmt(NULL,
&channel->cid,
"Bad shutdown scriptpubkey %s",
tal_hex(tmpctx, scriptpubkey));
/* Get connectd to send warning, and then allow reconnect. */
subd_send_msg(ld->connectd,
take(towire_connectd_peer_final_msg(NULL,
&channel->peer->id,
warning)));
channel_fail_reconnect(channel, "Bad shutdown scriptpubkey %s",
tal_hex(tmpctx, scriptpubkey));
return;
}
/* FIXME: Add to spec that we must allow repeated shutdown! */
tal_free(channel->shutdown_scriptpubkey[REMOTE]);
channel->shutdown_scriptpubkey[REMOTE] = scriptpubkey;
/* If we weren't already shutting down, we are now */
if (channel->state != CHANNELD_SHUTTING_DOWN)
channel_set_state(channel,

View File

@@ -15,6 +15,7 @@
#include <common/psbt_open.h>
#include <common/shutdown_scriptpubkey.h>
#include <common/type_to_string.h>
#include <common/wire_error.h>
#include <connectd/connectd_wiregen.h>
#include <errno.h>
#include <hsmd/capabilities.h>
@@ -1324,13 +1325,21 @@ static void handle_peer_wants_to_close(struct subd *dualopend,
* A receiving node:
*...
* - if the `scriptpubkey` is not in one of the above forms:
* - SHOULD fail the connection.
* - SHOULD send a `warning`
*/
if (!valid_shutdown_scriptpubkey(scriptpubkey, anysegwit, anchors)) {
channel_fail_permanent(channel,
REASON_PROTOCOL,
u8 *warning = towire_warningfmt(NULL,
&channel->cid,
"Bad shutdown scriptpubkey %s",
tal_hex(channel, scriptpubkey));
tal_hex(tmpctx, scriptpubkey));
/* Get connectd to send warning, and then allow reconnect. */
subd_send_msg(ld->connectd,
take(towire_connectd_peer_final_msg(NULL,
&channel->peer->id,
warning)));
channel_fail_reconnect(channel, "Bad shutdown scriptpubkey %s",
tal_hex(tmpctx, scriptpubkey));
return;
}

View File

@@ -329,24 +329,30 @@ void channel_errmsg(struct channel *channel,
*
* A sending node:
*...
* - when `channel_id` is 0:
* - MUST fail all channels with the receiving node.
* - MUST close the connection.
* - when sending `error`:
* - MUST fail the channel(s) referred to by the error message.
* - MAY set `channel_id` to all zero to indicate all channels.
*/
/* FIXME: Close if it's an all-channels error sent or rcvd */
/* BOLT #1:
*
* A sending node:
*...
* - when sending `error`:
* - MUST fail the channel referred to by the error message.
* - MUST fail the channel(s) referred to by the error message.
* - MAY set `channel_id` to all zero to indicate all channels.
*...
* The receiving node:
* - upon receiving `error`:
* - MUST fail the channel referred to by the error message,
* if that channel is with the sending node.
* - if `channel_id` is all zero:
* - MUST fail all channels with the sending node.
* - otherwise:
* - MUST fail the channel referred to by `channel_id`, if that channel is with the
* sending node.
*/
/* FIXME: We don't close all channels */
/* We should immediately forget the channel if we receive error during
* CHANNELD_AWAITING_LOCKIN if we are fundee. */
if (!err_for_them && channel->opener == REMOTE

View File

@@ -1945,7 +1945,8 @@ static bool channel_added_their_htlc(struct channel *channel,
/* BOLT #2:
*
* - receiving an `amount_msat` equal to 0, OR less than its own `htlc_minimum_msat`:
* - SHOULD fail the channel.
* - SHOULD send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (amount_msat_eq(added->amount, AMOUNT_MSAT(0))
|| amount_msat_less(added->amount, channel->our_config.htlc_minimum)) {
@@ -2280,7 +2281,8 @@ void peer_got_revoke(struct channel *channel, const u8 *msg)
*
* - if the `per_commitment_secret` was not generated by the protocol
* in [BOLT #3](03-transactions.md#per-commitment-secret-requirements):
* - MAY fail the channel.
* - MAY send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (!wallet_shachain_add_hash(ld->wallet,
&channel->their_shachain,
@@ -2488,6 +2490,7 @@ void htlcs_notify_new_block(struct lightningd *ld, u32 height)
*
* - if an HTLC which it offered is in either node's current
* commitment transaction, AND is past this timeout deadline:
* - SHOULD send an `error` to the receiving peer (if connected).
* - MUST fail the channel.
*/
/* FIXME: use db to look this up in one go (earliest deadline per-peer) */
@@ -2532,6 +2535,7 @@ void htlcs_notify_new_block(struct lightningd *ld, u32 height)
*...
* - if an HTLC it has fulfilled is in either node's current commitment
* transaction, AND is past this fulfillment deadline:
* - SHOULD send an `error` to the offering peer (if connected).
* - MUST fail the channel.
*/
do {

View File

@@ -1202,8 +1202,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state)
&err, &warning)) {
/* BOLT #1:
*
* - if no existing channel is referred to by the
* message:
* - if no existing channel is referred to by `channel_id`:
* - MUST ignore the message.
*/
/* In this case, is_peer_error returns true, but sets
@@ -1850,13 +1849,14 @@ static u8 *accepter_commits(struct state *state,
* The recipient:
* - if `signature` is incorrect OR non-compliant with LOW-S-standard
* rule...:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (!check_tx_sig(local_commit, 0, NULL, wscript,
&state->their_funding_pubkey, &remote_sig)) {
/* BOLT #1:
*
* ### The `error` Message
* ### The `error` and `warning` Messages
*...
* - when failure was caused by an invalid signature check:
* - SHOULD include the raw, hex-encoded transaction in reply
@@ -2575,14 +2575,15 @@ static u8 *opener_commits(struct state *state,
* The recipient:
* - if `signature` is incorrect OR non-compliant with LOW-S-standard
* rule...:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (!check_tx_sig(local_commit, 0, NULL, wscript,
&state->their_funding_pubkey,
&remote_sig)) {
/* BOLT #1:
*
* ### The `error` Message
* ### The `error` and `warning` Messages
*...
* - when failure was caused by an invalid signature check:
* - SHOULD include the raw, hex-encoded transaction in reply
@@ -3588,7 +3589,7 @@ static void do_reconnect_dance(struct state *state)
/* BOLT #2:
* - if it has not sent `revoke_and_ack`, AND
* `next_revocation_number` is not equal to 0:
* - SHOULD fail the channel.
* - SHOULD send an `error` and fail the channel.
*/
/* It's possible that we've opened an outdated copy of the
* database, and the peer is very much ahead of us.

View File

@@ -192,8 +192,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state,
&err, &warning)) {
/* BOLT #1:
*
* - if no existing channel is referred to by the
* message:
* - if no existing channel is referred to by `channel_id`:
* - MUST ignore the message.
*/
/* In this case, is_peer_error returns true, but sets
@@ -1107,7 +1106,8 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg)
* The recipient:
* - if `signature` is incorrect OR non-compliant with LOW-S-standard
* rule...:
* - MUST fail the channel.
* - MUST send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
local_commit = initial_channel_tx(state, &wscript, state->channel,
&state->first_per_commitment_point[LOCAL],
@@ -1125,7 +1125,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg)
&theirsig)) {
/* BOLT #1:
*
* ### The `error` Message
* ### The `error` and `warning` Messages
*...
* - when failure was caused by an invalid signature check:
* - SHOULD include the raw, hex-encoded transaction in reply

View File

@@ -1,5 +1,4 @@
from fixtures import * # noqa: F401,F403
from flaky import flaky
from pyln.client import RpcError, Millisatoshi
from shutil import copyfile
from pyln.testing.utils import SLOW_MACHINE
@@ -3186,31 +3185,27 @@ def test_shutdown(node_factory):
l1.rpc.stop()
@flaky
@pytest.mark.developer("needs to set upfront_shutdown_script")
def test_option_upfront_shutdown_script(node_factory, bitcoind, executor):
# There's a workaround in channeld, that it treats incoming errors
# before both sides are locked in as warnings; this happens in
# this test, so l1 reports the error as a warning!
l1 = node_factory.get_node(start=False, allow_warning=True)
# Insist on upfront script we're not going to match.
# '0014' + l1.rpc.call('dev-listaddrs', [10])['addresses'][-1]['bech32_redeemscript']
l1.daemon.env["DEV_OPENINGD_UPFRONT_SHUTDOWN_SCRIPT"] = "00143d43d226bcc27019ade52d7a3dc52a7ac1be28b8"
l1.start()
l2 = node_factory.get_node()
l2 = node_factory.get_node(allow_warning=True)
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
l1.fundchannel(l2, 1000000, False)
# This will block, as l12 will send an error but l2 will retry.
# This will block, as l1 will send a warning but l2 will retry.
fut = executor.submit(l1.rpc.close, l2.info['id'])
# l2 will close unilaterally when it dislikes shutdown script.
l1.daemon.wait_for_log(r'scriptpubkey .* is not as agreed upfront \(00143d43d226bcc27019ade52d7a3dc52a7ac1be28b8\)')
# l2 will send a warning when it dislikes shutdown script.
l1.daemon.wait_for_log(r'WARNING.*scriptpubkey .* is not as agreed upfront \(00143d43d226bcc27019ade52d7a3dc52a7ac1be28b8\)')
# Clear channel.
wait_for(lambda: len(bitcoind.rpc.getrawmempool()) != 0)
bitcoind.generate_block(1)
# Close from l2's side and clear channel.
l2.rpc.close(l1.info['id'], unilateraltimeout=1)
bitcoind.generate_block(1, wait_for_mempool=1)
fut.result(TIMEOUT)
wait_for(lambda: [c['state'] for c in only_one(l1.rpc.listpeers()['peers'])['channels']] == ['ONCHAIN'])
wait_for(lambda: [c['state'] for c in only_one(l2.rpc.listpeers()['peers'])['channels']] == ['ONCHAIN'])
@@ -3219,14 +3214,12 @@ def test_option_upfront_shutdown_script(node_factory, bitcoind, executor):
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
l1.fundchannel(l2, 1000000, False)
l2.rpc.close(l1.info['id'])
l2.rpc.close(l1.info['id'], unilateraltimeout=5)
# l2 will close unilaterally when it dislikes shutdown script.
l1.daemon.wait_for_log(r'scriptpubkey .* is not as agreed upfront \(00143d43d226bcc27019ade52d7a3dc52a7ac1be28b8\)')
# l2 will send warning unilaterally when it dislikes shutdown script.
l1.daemon.wait_for_log(r'WARNING.*scriptpubkey .* is not as agreed upfront \(00143d43d226bcc27019ade52d7a3dc52a7ac1be28b8\)')
# Clear channel.
wait_for(lambda: len(bitcoind.rpc.getrawmempool()) != 0)
bitcoind.generate_block(1)
bitcoind.generate_block(1, wait_for_mempool=1)
wait_for(lambda: [c['state'] for c in only_one(l1.rpc.listpeers()['peers'])['channels']] == ['ONCHAIN', 'ONCHAIN'])
wait_for(lambda: [c['state'] for c in only_one(l2.rpc.listpeers()['peers'])['channels']] == ['ONCHAIN', 'ONCHAIN'])

View File

@@ -1,13 +0,0 @@
--- wire/peer_exp_wire.csv 2021-01-14 11:00:27.526336550 +1030
+++ - 2021-01-21 15:31:37.071118999 +1030
@@ -10,6 +10,10 @@
msgdata,error,channel_id,channel_id,
msgdata,error,len,u16,
msgdata,error,data,byte,len
+msgtype,warning,1
+msgdata,warning,channel_id,channel_id,
+msgdata,warning,len,u16,
+msgdata,warning,data,byte,len
msgtype,ping,18
msgdata,ping,num_pong_bytes,u16,
msgdata,ping,byteslen,u16,