lnpeer: warnings for shutdown and open_channel
This commit is contained in:
@@ -53,7 +53,7 @@ from .lnutil import (Outpoint, LocalConfig, RemoteConfig, Keypair, OnlyPubkeyKey
|
||||
ShortChannelID, map_htlcs_to_ctx_output_idxs, LNPeerAddr,
|
||||
fee_for_htlc_output, offered_htlc_trim_threshold_sat,
|
||||
received_htlc_trim_threshold_sat, make_commitment_output_to_remote_address,
|
||||
ChannelType)
|
||||
ChannelType, LNProtocolWarning)
|
||||
from .lnsweep import create_sweeptxs_for_our_ctx, create_sweeptxs_for_their_ctx
|
||||
from .lnsweep import create_sweeptx_for_their_revoked_htlc, SweepInfo
|
||||
from .lnhtlc import HTLCManager
|
||||
@@ -981,7 +981,9 @@ class Channel(AbstractChannel):
|
||||
preimage_hex = pending_local_commitment.serialize_preimage(0)
|
||||
pre_hash = sha256d(bfh(preimage_hex))
|
||||
if not ecc.verify_signature(self.config[REMOTE].multisig_key.pubkey, sig, pre_hash):
|
||||
raise Exception(f'failed verifying signature of our updated commitment transaction: {bh2u(sig)} preimage is {preimage_hex}')
|
||||
raise LNProtocolWarning(
|
||||
f'failed verifying signature of our updated commitment transaction: '
|
||||
f'{bh2u(sig)} preimage is {preimage_hex}, rawtx: {pending_local_commitment.serialize()}')
|
||||
|
||||
htlc_sigs_string = b''.join(htlc_sigs)
|
||||
|
||||
@@ -993,7 +995,7 @@ class Channel(AbstractChannel):
|
||||
subject=LOCAL,
|
||||
ctn=next_local_ctn)
|
||||
if len(htlc_to_ctx_output_idx_map) != len(htlc_sigs):
|
||||
raise Exception(f'htlc sigs failure. recv {len(htlc_sigs)} sigs, expected {len(htlc_to_ctx_output_idx_map)}')
|
||||
raise LNProtocolWarning(f'htlc sigs failure. recv {len(htlc_sigs)} sigs, expected {len(htlc_to_ctx_output_idx_map)}')
|
||||
for (direction, htlc), (ctx_output_idx, htlc_relative_idx) in htlc_to_ctx_output_idx_map.items():
|
||||
htlc_sig = htlc_sigs[htlc_relative_idx]
|
||||
self._verify_htlc_sig(htlc=htlc,
|
||||
@@ -1021,7 +1023,7 @@ class Channel(AbstractChannel):
|
||||
pre_hash = sha256d(bfh(htlc_tx.serialize_preimage(0)))
|
||||
remote_htlc_pubkey = derive_pubkey(self.config[REMOTE].htlc_basepoint.pubkey, pcp)
|
||||
if not ecc.verify_signature(remote_htlc_pubkey, htlc_sig, pre_hash):
|
||||
raise Exception(f'failed verifying HTLC signatures: {htlc} {htlc_direction}')
|
||||
raise LNProtocolWarning(f'failed verifying HTLC signatures: {htlc} {htlc_direction}, rawtx: {htlc_tx.serialize()}')
|
||||
|
||||
def get_remote_htlc_sig_for_htlc(self, *, htlc_relative_idx: int) -> bytes:
|
||||
data = self.config[LOCAL].current_htlc_signatures
|
||||
|
||||
@@ -42,7 +42,7 @@ from .lnutil import (Outpoint, LocalConfig, RECEIVED, UpdateAddHtlc, ChannelConf
|
||||
LightningPeerConnectionClosed, HandshakeFailed,
|
||||
RemoteMisbehaving, ShortChannelID,
|
||||
IncompatibleLightningFeatures, derive_payment_secret_from_payment_preimage,
|
||||
UpfrontShutdownScriptViolation, ChannelType)
|
||||
ChannelType, LNProtocolWarning)
|
||||
from .lnutil import FeeUpdate, channel_id_from_funding_tx
|
||||
from .lntransport import LNTransport, LNTransportBase
|
||||
from .lnmsg import encode_msg, decode_msg, UnknownOptionalMsgType
|
||||
@@ -861,7 +861,10 @@ class Peer(Logger):
|
||||
payload = await self.wait_for_message('funding_signed', channel_id)
|
||||
self.logger.info('received funding_signed')
|
||||
remote_sig = payload['signature']
|
||||
chan.receive_new_commitment(remote_sig, [])
|
||||
try:
|
||||
chan.receive_new_commitment(remote_sig, [])
|
||||
except LNProtocolWarning as e:
|
||||
await self.send_warning(channel_id, message=str(e), close_connection=True)
|
||||
chan.open_with_first_pcp(remote_per_commitment_point, remote_sig)
|
||||
chan.set_state(ChannelState.OPENING)
|
||||
self.lnworker.add_new_channel(chan)
|
||||
@@ -1020,7 +1023,10 @@ class Peer(Logger):
|
||||
if isinstance(self.transport, LNTransport):
|
||||
chan.add_or_update_peer_addr(self.transport.peer_addr)
|
||||
remote_sig = funding_created['signature']
|
||||
chan.receive_new_commitment(remote_sig, [])
|
||||
try:
|
||||
chan.receive_new_commitment(remote_sig, [])
|
||||
except LNProtocolWarning as e:
|
||||
await self.send_warning(channel_id, message=str(e), close_connection=True)
|
||||
sig_64, _ = chan.sign_next_commitment()
|
||||
self.send_message('funding_signed',
|
||||
channel_id=channel_id,
|
||||
@@ -1868,12 +1874,18 @@ class Peer(Logger):
|
||||
return txid
|
||||
|
||||
async def on_shutdown(self, chan: Channel, payload):
|
||||
# TODO: A receiving node: if it hasn't received a funding_signed (if it is a
|
||||
# funder) or a funding_created (if it is a fundee):
|
||||
# SHOULD send an error and fail the channel.
|
||||
their_scriptpubkey = payload['scriptpubkey']
|
||||
their_upfront_scriptpubkey = chan.config[REMOTE].upfront_shutdown_script
|
||||
# BOLT-02 check if they use the upfront shutdown script they advertized
|
||||
if their_upfront_scriptpubkey:
|
||||
if self.is_upfront_shutdown_script() and their_upfront_scriptpubkey:
|
||||
if not (their_scriptpubkey == their_upfront_scriptpubkey):
|
||||
raise UpfrontShutdownScriptViolation("remote didn't use upfront shutdown script it commited to in channel opening")
|
||||
await self.send_warning(
|
||||
chan.channel_id,
|
||||
"remote didn't use upfront shutdown script it commited to in channel opening",
|
||||
close_connection=True)
|
||||
else:
|
||||
# BOLT-02 restrict the scriptpubkey to some templates:
|
||||
if self.is_shutdown_anysegwit() and match_script_against_template(their_scriptpubkey, transaction.SCRIPTPUBKEY_TEMPLATE_ANYSEGWIT):
|
||||
@@ -1881,7 +1893,10 @@ class Peer(Logger):
|
||||
elif match_script_against_template(their_scriptpubkey, transaction.SCRIPTPUBKEY_TEMPLATE_WITNESS_V0):
|
||||
pass
|
||||
else:
|
||||
raise Exception(f'scriptpubkey in received shutdown message does not conform to any template: {their_scriptpubkey.hex()}')
|
||||
await self.send_warning(
|
||||
chan.channel_id,
|
||||
f'scriptpubkey in received shutdown message does not conform to any template: {their_scriptpubkey.hex()}',
|
||||
close_connection=True)
|
||||
|
||||
chan_id = chan.channel_id
|
||||
if chan_id in self.shutdown_received:
|
||||
|
||||
@@ -351,7 +351,6 @@ class UnableToDeriveSecret(LightningError): pass
|
||||
class HandshakeFailed(LightningError): pass
|
||||
class ConnStringFormatError(LightningError): pass
|
||||
class RemoteMisbehaving(LightningError): pass
|
||||
class UpfrontShutdownScriptViolation(RemoteMisbehaving): pass
|
||||
|
||||
class NotFoundChanAnnouncementForUpdate(Exception): pass
|
||||
class InvalidGossipMsg(Exception):
|
||||
|
||||
@@ -22,9 +22,8 @@ from electrum import simple_config, lnutil
|
||||
from electrum.lnaddr import lnencode, LnAddr, lndecode
|
||||
from electrum.bitcoin import COIN, sha256
|
||||
from electrum.util import bh2u, create_and_start_event_loop, NetworkRetryManager, bfh, OldTaskGroup
|
||||
from electrum.lnpeer import Peer, UpfrontShutdownScriptViolation
|
||||
from electrum.lnpeer import Peer
|
||||
from electrum.lnutil import LNPeerAddr, Keypair, privkey_to_pubkey
|
||||
from electrum.lnutil import LightningPeerConnectionClosed, RemoteMisbehaving
|
||||
from electrum.lnutil import PaymentFailure, LnFeatures, HTLCOwner
|
||||
from electrum.lnchannel import ChannelState, PeerState, Channel
|
||||
from electrum.lnrouter import LNPathFinder, PathEdge, LNPathInconsistent
|
||||
@@ -1201,7 +1200,7 @@ class TestPeer(TestCaseForTestnet):
|
||||
gath = asyncio.gather(*coros)
|
||||
await gath
|
||||
|
||||
with self.assertRaises(UpfrontShutdownScriptViolation):
|
||||
with self.assertRaises(GracefulDisconnect):
|
||||
run(test())
|
||||
|
||||
# bob sends the same upfront_shutdown_script has he announced
|
||||
|
||||
Reference in New Issue
Block a user