notify: `channel_state_changed` now receives notice when channel opens

Previously we wouldn't notify when a channel moves into state
"CHANNELD_AWAITING_LOCKIN", as this is the original state (so there's
no movement btw states). This meant that it's impossible to track when a
channel's commitment txs have been exchanged and we're waiting for
onchain confirmation.

It's useful to have notice of this initialization though, all in one
place so that the `channel_state_changed` notification can successfully
track the entire lifecycle of a channel, from inception to close.

Note that for v2 "dual-funded" channels, we already notify at the same place, at
"DUALOPEND_AWAITING_LOCKIN" (the initial state for a dualopend channel
is "DUALOPEND_OPEN_INIT" -- this is the only state we don't get notified
at now...)

Changelog-Added: Plugins: `channel_state_changed` now triggers for a v1 channel's initial "CHANNELD_AWAITING_LOCKIN" state transition (from prior state "unknown")
This commit is contained in:
niftynei 2022-07-06 10:01:58 -05:00 committed by neil saitug
parent bdefbabbef
commit d284b98911
2 changed files with 43 additions and 28 deletions

View File

@ -102,6 +102,7 @@ wallet_commit_channel(struct lightningd *ld,
u64 static_remotekey_start;
u32 lease_start_blockheight = 0; /* No leases on v1 */
struct short_channel_id *alias_local;
struct timeabs timestamp;
/* We cannot both be the fundee *and* have a `fundchannel_start`
* command running!
@ -226,6 +227,17 @@ wallet_commit_channel(struct lightningd *ld,
/* Now we finally put it in the database. */
wallet_channel_insert(ld->wallet, channel);
/* Notify that channel state changed (from non existant to existant) */
timestamp = time_now();
notify_channel_state_changed(ld, &channel->peer->id,
&channel->cid,
channel->scid, /* NULL */
&timestamp,
0, /* No prior state */
channel->state,
channel->state_change_cause,
"new channel opened");
return channel;
}

View File

@ -777,27 +777,29 @@ def test_channel_state_changed_bilateral(node_factory, bitcoind):
event1 = wait_for_event(l1)
event2 = wait_for_event(l2)
if l1.config('experimental-dual-fund'):
# Dual funded channels have an extra state change
assert(event1['peer_id'] == l2_id) # we only test these IDs the first time
assert(event1['channel_id'] == cid)
assert(event1['short_channel_id'] is None)
assert(event1['old_state'] == "DUALOPEND_OPEN_INIT")
assert(event1['new_state'] == "DUALOPEND_AWAITING_LOCKIN")
assert(event1['cause'] == "user")
assert(event1['message'] == "Sigs exchanged, waiting for lock-in")
event1 = wait_for_event(l1)
assert(event2['peer_id'] == l1_id) # we only test these IDs the first time
assert(event2['channel_id'] == cid)
assert(event2['short_channel_id'] is None)
assert(event2['old_state'] == "DUALOPEND_OPEN_INIT")
assert(event2['new_state'] == "DUALOPEND_AWAITING_LOCKIN")
assert(event2['cause'] == "remote")
assert(event2['message'] == "Sigs exchanged, waiting for lock-in")
event2 = wait_for_event(l2)
assert(event1['peer_id'] == l2_id) # we only test these IDs the first time
assert(event1['channel_id'] == cid)
assert(event1['short_channel_id'] is None) # None until locked in
assert(event1['cause'] == "user")
assert(event2['peer_id'] == l1_id) # we only test these IDs the first time
assert(event2['channel_id'] == cid)
assert(event2['short_channel_id'] is None) # None until locked in
assert(event2['cause'] == "remote")
for ev in [event1, event2]:
# Dual funded channels
if l1.config('experimental-dual-fund'):
assert(ev['old_state'] == "DUALOPEND_OPEN_INIT")
assert(ev['new_state'] == "DUALOPEND_AWAITING_LOCKIN")
assert(ev['message'] == "Sigs exchanged, waiting for lock-in")
else:
assert(ev['old_state'] == "unknown")
assert(ev['new_state'] == "CHANNELD_AWAITING_LOCKIN")
assert(ev['message'] == "new channel opened")
event1 = wait_for_event(l1)
event2 = wait_for_event(l2)
assert(event1['short_channel_id'] == scid)
if l1.config('experimental-dual-fund'):
assert(event1['old_state'] == "DUALOPEND_AWAITING_LOCKIN")
@ -807,8 +809,6 @@ def test_channel_state_changed_bilateral(node_factory, bitcoind):
assert(event1['cause'] == "user")
assert(event1['message'] == "Lockin complete")
assert(event2['peer_id'] == l1_id)
assert(event2['channel_id'] == cid)
assert(event2['short_channel_id'] == scid)
if l1.config('experimental-dual-fund'):
assert(event2['old_state'] == "DUALOPEND_AWAITING_LOCKIN")
@ -911,18 +911,21 @@ def test_channel_state_changed_unilateral(node_factory, bitcoind):
return event
event2 = wait_for_event(l2)
assert(event2['peer_id'] == l1_id)
assert(event2['channel_id'] == cid)
assert(event2['short_channel_id'] is None)
assert(event2['cause'] == "remote")
if l2.config('experimental-dual-fund'):
assert(event2['peer_id'] == l1_id)
assert(event2['channel_id'] == cid)
assert(event2['short_channel_id'] is None)
assert(event2['old_state'] == "DUALOPEND_OPEN_INIT")
assert(event2['new_state'] == "DUALOPEND_AWAITING_LOCKIN")
assert(event2['cause'] == "remote")
assert(event2['message'] == "Sigs exchanged, waiting for lock-in")
event2 = wait_for_event(l2)
else:
assert(event2['old_state'] == "unknown")
assert(event2['new_state'] == "CHANNELD_AWAITING_LOCKIN")
assert(event2['message'] == "new channel opened")
assert(event2['peer_id'] == l1_id) # we only test these IDs the first time
assert(event2['channel_id'] == cid)
event2 = wait_for_event(l2)
assert(event2['short_channel_id'] == scid)
if l2.config('experimental-dual-fund'):
assert(event2['old_state'] == "DUALOPEND_AWAITING_LOCKIN")