openingd: check upfront shutdown script.

The spec doesn't say to do this, but it makes sense, otherwise
they'll never be able to mutually close the channel.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2021-02-19 14:52:02 +10:30
parent 66dda32da2
commit 26627bdf7d
3 changed files with 33 additions and 4 deletions

View File

@ -75,6 +75,7 @@ OPENINGD_COMMON_OBJS := \
common/pseudorand.o \ common/pseudorand.o \
common/read_peer_msg.o \ common/read_peer_msg.o \
common/setup.o \ common/setup.o \
common/shutdown_scriptpubkey.o \
common/status.o \ common/status.o \
common/status_wire.o \ common/status_wire.o \
common/subdaemon.o \ common/subdaemon.o \

View File

@ -34,6 +34,7 @@
#include <common/peer_status_wiregen.h> #include <common/peer_status_wiregen.h>
#include <common/penalty_base.h> #include <common/penalty_base.h>
#include <common/read_peer_msg.h> #include <common/read_peer_msg.h>
#include <common/shutdown_scriptpubkey.h>
#include <common/status.h> #include <common/status.h>
#include <common/subdaemon.h> #include <common/subdaemon.h>
#include <common/type_to_string.h> #include <common/type_to_string.h>
@ -321,6 +322,20 @@ static bool setup_channel_funder(struct state *state)
return true; return true;
} }
static void set_remote_upfront_shutdown(struct state *state,
u8 *shutdown_scriptpubkey STEALS)
{
state->upfront_shutdown_script[REMOTE]
= tal_steal(state, shutdown_scriptpubkey);
if (shutdown_scriptpubkey
&& !valid_shutdown_scriptpubkey(shutdown_scriptpubkey))
peer_failed_err(state->pps,
&state->channel_id,
"Unacceptable upfront_shutdown_script %s",
tal_hex(tmpctx, shutdown_scriptpubkey));
}
/* We start the 'open a channel' negotation with the supplied peer, but /* We start the 'open a channel' negotation with the supplied peer, but
* stop when we get to the part where we need the funding txid */ * stop when we get to the part where we need the funding txid */
static u8 *funder_channel_start(struct state *state, u8 channel_flags) static u8 *funder_channel_start(struct state *state, u8 channel_flags)
@ -404,8 +419,7 @@ static u8 *funder_channel_start(struct state *state, u8 channel_flags)
&state->channel_id, &state->channel_id,
"Parsing accept_channel %s", tal_hex(msg, msg)); "Parsing accept_channel %s", tal_hex(msg, msg));
} }
state->upfront_shutdown_script[REMOTE] set_remote_upfront_shutdown(state, accept_tlvs->upfront_shutdown_script);
= tal_steal(state, accept_tlvs->upfront_shutdown_script);
/* BOLT #2: /* BOLT #2:
* *
@ -764,8 +778,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg)
peer_failed_err(state->pps, peer_failed_err(state->pps,
&state->channel_id, &state->channel_id,
"Parsing open_channel %s", tal_hex(tmpctx, open_channel_msg)); "Parsing open_channel %s", tal_hex(tmpctx, open_channel_msg));
state->upfront_shutdown_script[REMOTE] set_remote_upfront_shutdown(state, open_tlvs->upfront_shutdown_script);
= tal_steal(state, open_tlvs->upfront_shutdown_script);
/* BOLT #2: /* BOLT #2:
* *

View File

@ -2594,3 +2594,18 @@ def test_option_upfront_shutdown_script(node_factory, bitcoind, executor):
l1.rpc.fundchannel(l2.info['id'], 1000000) l1.rpc.fundchannel(l2.info['id'], 1000000)
l1.rpc.close(l2.info['id']) l1.rpc.close(l2.info['id'])
wait_for(lambda: sorted([c['state'] for c in only_one(l1.rpc.listpeers()['peers'])['channels']]) == ['CLOSINGD_COMPLETE', 'ONCHAIN', 'ONCHAIN']) wait_for(lambda: sorted([c['state'] for c in only_one(l1.rpc.listpeers()['peers'])['channels']]) == ['CLOSINGD_COMPLETE', 'ONCHAIN', 'ONCHAIN'])
@unittest.skipIf(not DEVELOPER, "needs to set upfront_shutdown_script")
def test_invalid_upfront_shutdown_script(node_factory, bitcoind, executor):
l1, l2 = node_factory.line_graph(2, fundchannel=False)
l1 = node_factory.get_node(start=False, allow_warning=True)
# Insist on upfront script we're not going to match.
l1.daemon.env["DEV_OPENINGD_UPFRONT_SHUTDOWN_SCRIPT"] = "76a91404b61f7dc1ea0dc99424464cc4064dc564d91e8988ac00"
l1.start()
l2 = node_factory.get_node()
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
with pytest.raises(RpcError, match=r'Unacceptable upfront_shutdown_script'):
l1.fundchannel(l2, 1000000, False)