@@ -387,7 +387,9 @@ def on_init(self, payload):
387
387
if their_networks :
388
388
their_chains = list (chunks (their_networks ["chains" ], 32 ))
389
389
if constants .net .rev_genesis_bytes () not in their_chains :
390
- raise GracefulDisconnect (f"no common chain found with remote. (they sent: { their_chains } )" )
390
+ raise GracefulDisconnect (f"no common chain found with remote. "
391
+ f"(they sent: { [chain .hex () for chain in their_chains ]} ),"
392
+ f" our chain: { constants .net .rev_genesis_bytes ().hex ()} " )
391
393
# all checks passed
392
394
self .lnworker .on_peer_successfully_established (self )
393
395
self ._received_init = True
@@ -963,6 +965,7 @@ async def channel_establishment_flow(
963
965
)
964
966
chan .storage ['funding_inputs' ] = [txin .prevout .to_json () for txin in funding_tx .inputs ()]
965
967
chan .storage ['has_onchain_backup' ] = has_onchain_backup
968
+ chan .storage ['init_timestamp' ] = int (time .time ())
966
969
if isinstance (self .transport , LNTransport ):
967
970
chan .add_or_update_peer_addr (self .transport .peer_addr )
968
971
sig_64 , _ = chan .sign_next_commitment ()
@@ -1023,27 +1026,13 @@ async def on_open_channel(self, payload):
1023
1026
1024
1027
Channel configurations are initialized in this method.
1025
1028
"""
1026
- if self .lnworker .has_recoverable_channels ():
1027
- # FIXME: we might want to keep the connection open
1028
- raise Exception ('not accepting channels' )
1029
+
1029
1030
# <- open_channel
1030
1031
if payload ['chain_hash' ] != constants .net .rev_genesis_bytes ():
1031
1032
raise Exception ('wrong chain_hash' )
1032
- funding_sat = payload ['funding_satoshis' ]
1033
- push_msat = payload ['push_msat' ]
1034
- feerate = payload ['feerate_per_kw' ] # note: we are not validating this
1035
- temp_chan_id = payload ['temporary_channel_id' ]
1036
- # store the temp id now, so that it is recognized for e.g. 'error' messages
1037
- # TODO: this is never cleaned up; the dict grows unbounded until disconnect
1038
- self .temp_id_to_id [temp_chan_id ] = None
1039
1033
1040
1034
open_channel_tlvs = payload .get ('open_channel_tlvs' )
1041
1035
channel_type = open_channel_tlvs .get ('channel_type' ) if open_channel_tlvs else None
1042
-
1043
- channel_opening_fee = open_channel_tlvs .get ('channel_opening_fee' ) if open_channel_tlvs else None
1044
- if channel_opening_fee :
1045
- # todo check that the fee is reasonable
1046
- pass
1047
1036
# The receiving node MAY fail the channel if:
1048
1037
# option_channel_type was negotiated but the message doesn't include a channel_type
1049
1038
if self .is_channel_type () and channel_type is None :
@@ -1054,6 +1043,26 @@ async def on_open_channel(self, payload):
1054
1043
channel_type = ChannelType .from_bytes (channel_type ['type' ], byteorder = 'big' ).discard_unknown_and_check ()
1055
1044
if not channel_type .complies_with_features (self .features ):
1056
1045
raise Exception ("sender has sent a channel type we don't support" )
1046
+ is_zeroconf = channel_type & channel_type .OPTION_ZEROCONF
1047
+ if is_zeroconf and not self .network .config .ZEROCONF_TRUSTED_NODE .startswith (self .pubkey .hex ()):
1048
+ raise Exception (f"not accepting zeroconf from node { self .pubkey } " )
1049
+
1050
+ if self .lnworker .has_recoverable_channels () and not is_zeroconf :
1051
+ # FIXME: we might want to keep the connection open
1052
+ raise Exception ('not accepting channels' )
1053
+ funding_sat = payload ['funding_satoshis' ]
1054
+ push_msat = payload ['push_msat' ]
1055
+ feerate = payload ['feerate_per_kw' ] # note: we are not validating this
1056
+ temp_chan_id = payload ['temporary_channel_id' ]
1057
+ # store the temp id now, so that it is recognized for e.g. 'error' messages
1058
+ # TODO: this is never cleaned up; the dict grows unbounded until disconnect
1059
+ self .temp_id_to_id [temp_chan_id ] = None
1060
+
1061
+
1062
+ channel_opening_fee = open_channel_tlvs .get ('channel_opening_fee' ) if open_channel_tlvs else None
1063
+ if channel_opening_fee :
1064
+ # todo check that the fee is reasonable
1065
+ pass
1057
1066
1058
1067
if self .use_anchors ():
1059
1068
multisig_funding_keypair = lnutil .derive_multisig_funding_key_if_they_opened (
@@ -1115,9 +1124,6 @@ async def on_open_channel(self, payload):
1115
1124
per_commitment_point_first = secret_to_pubkey (
1116
1125
int .from_bytes (per_commitment_secret_first , 'big' ))
1117
1126
1118
- is_zeroconf = channel_type & channel_type .OPTION_ZEROCONF
1119
- if is_zeroconf and not self .network .config .ZEROCONF_TRUSTED_NODE .startswith (self .pubkey .hex ()):
1120
- raise Exception (f"not accepting zeroconf from node { self .pubkey } " )
1121
1127
min_depth = 0 if is_zeroconf else 3
1122
1128
1123
1129
accept_channel_tlvs = {
@@ -1870,7 +1876,7 @@ def log_fail_reason(reason: str):
1870
1876
next_chan = self .lnworker .get_channel_by_short_id (next_chan_scid )
1871
1877
1872
1878
if self .lnworker .features .supports (LnFeatures .OPTION_ZEROCONF_OPT ):
1873
- next_peer = self .lnworker .get_peer_by_scid_alias (next_chan_scid )
1879
+ next_peer = self .lnworker .get_peer_by_static_jit_scid_alias (next_chan_scid )
1874
1880
else :
1875
1881
next_peer = None
1876
1882
@@ -1881,6 +1887,9 @@ def log_fail_reason(reason: str):
1881
1887
if next_chan .can_pay (next_amount_msat_htlc ):
1882
1888
break
1883
1889
else :
1890
+ htlc_id = serialize_htlc_key (incoming_chan .get_scid_or_local_alias (), htlc .htlc_id )
1891
+ # prevent settling the htlc until the channel opening was successfull so we can fail it if needed
1892
+ self .lnworker .dont_settle_htlc_keys [htlc_id ] = None
1884
1893
return await self .lnworker .open_channel_just_in_time (
1885
1894
next_peer = next_peer ,
1886
1895
next_amount_msat_htlc = next_amount_msat_htlc ,
@@ -1954,6 +1963,7 @@ async def maybe_forward_trampoline(
1954
1963
outer_onion : ProcessedOnionPacket ,
1955
1964
trampoline_onion : ProcessedOnionPacket ,
1956
1965
fw_payment_key : str ,
1966
+ inc_htlc_key : str ,
1957
1967
) -> None :
1958
1968
1959
1969
forwarding_enabled = self .network .config .EXPERIMENTAL_LN_FORWARD_PAYMENTS
@@ -2016,7 +2026,7 @@ async def maybe_forward_trampoline(
2016
2026
2017
2027
# do we have a connection to the node?
2018
2028
next_peer = self .lnworker .peers .get (outgoing_node_id )
2019
- if next_peer and next_peer .accepts_zeroconf ():
2029
+ if next_peer and next_peer .accepts_zeroconf () and self . lnworker . features . supports ( LnFeatures . OPTION_ZEROCONF_OPT ) :
2020
2030
self .logger .info (f'JIT: found next_peer' )
2021
2031
for next_chan in next_peer .channels .values ():
2022
2032
if next_chan .can_pay (amt_to_forward ):
@@ -2043,6 +2053,7 @@ async def maybe_forward_trampoline(
2043
2053
payment_secret = payment_secret ,
2044
2054
trampoline_onion = next_trampoline_onion ,
2045
2055
)
2056
+ self .lnworker .dont_settle_htlc_keys [inc_htlc_key ] = None
2046
2057
await self .lnworker .open_channel_just_in_time (
2047
2058
next_peer = next_peer ,
2048
2059
next_amount_msat_htlc = amt_to_forward ,
@@ -2182,16 +2193,16 @@ def maybe_fulfill_htlc(
2182
2193
Decide what to do with an HTLC: return preimage if it can be fulfilled, forwarding callback if it can be forwarded.
2183
2194
Return (preimage, (payment_key, callback)) with at most a single element not None.
2184
2195
"""
2196
+ htlc_key = serialize_htlc_key (chan .get_scid_or_local_alias (), htlc .htlc_id )
2185
2197
if not processed_onion .are_we_final :
2186
2198
if not self .lnworker .enable_htlc_forwarding :
2187
2199
return None , None
2188
2200
# use the htlc key if we are forwarding
2189
- payment_key = serialize_htlc_key (chan .get_scid_or_local_alias (), htlc .htlc_id )
2190
2201
callback = lambda : self .maybe_forward_htlc (
2191
2202
incoming_chan = chan ,
2192
2203
htlc = htlc ,
2193
2204
processed_onion = processed_onion )
2194
- return None , (payment_key , callback )
2205
+ return None , (htlc_key , callback )
2195
2206
2196
2207
def log_fail_reason (reason : str ):
2197
2208
self .logger .info (
@@ -2260,7 +2271,8 @@ def log_fail_reason(reason: str):
2260
2271
inc_cltv_abs = htlc .cltv_abs , # TODO: use max or enforce same value across mpp parts
2261
2272
outer_onion = processed_onion ,
2262
2273
trampoline_onion = trampoline_onion ,
2263
- fw_payment_key = payment_key )
2274
+ fw_payment_key = payment_key ,
2275
+ inc_htlc_key = htlc_key )
2264
2276
return None , (payment_key , callback )
2265
2277
2266
2278
# TODO don't accept payments twice for same invoice
@@ -2853,10 +2865,11 @@ async def wrapped_callback():
2853
2865
forwarding_coro = forwarding_callback ()
2854
2866
try :
2855
2867
next_htlc = await forwarding_coro
2856
- if next_htlc :
2868
+ if next_htlc and payment_key in self . lnworker . active_forwardings :
2857
2869
htlc_key = serialize_htlc_key (chan .get_scid_or_local_alias (), htlc .htlc_id )
2858
2870
self .lnworker .active_forwardings [payment_key ].append (next_htlc )
2859
2871
self .lnworker .downstream_to_upstream_htlc [next_htlc ] = htlc_key
2872
+ self .lnworker .dont_settle_htlc_keys .pop (htlc_key , None )
2860
2873
except OnionRoutingFailure as e :
2861
2874
if len (self .lnworker .active_forwardings [payment_key ]) == 0 :
2862
2875
self .lnworker .save_forwarding_failure (payment_key , failure_message = e )
@@ -2890,7 +2903,7 @@ async def wrapped_callback():
2890
2903
return None , None , error_bytes
2891
2904
if error_reason :
2892
2905
raise error_reason
2893
- if preimage :
2906
+ if preimage and forwarding_key not in self . lnworker . dont_settle_htlc_keys :
2894
2907
return preimage , None , None
2895
2908
return None , None , None
2896
2909
0 commit comments