mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-29 08:21:27 +00:00
ln feature bits: validate transitive feature deps everywhere
This commit is contained in:
parent
94e3c078f8
commit
71635216df
4 changed files with 30 additions and 17 deletions
|
@ -39,7 +39,7 @@ from . import constants
|
|||
from .util import bh2u, profiler, get_headers_dir, bfh, is_ip_address, list_enabled_bits
|
||||
from .logging import Logger
|
||||
from .lnutil import (LNPeerAddr, format_short_channel_id, ShortChannelID,
|
||||
UnknownEvenFeatureBits, validate_features)
|
||||
validate_features, IncompatibleOrInsaneFeatures)
|
||||
from .lnverifier import LNChannelVerifier, verify_sig_for_channel_update
|
||||
from .lnmsg import decode_msg
|
||||
|
||||
|
@ -331,8 +331,8 @@ class ChannelDB(SqlDB):
|
|||
continue
|
||||
try:
|
||||
channel_info = ChannelInfo.from_msg(msg)
|
||||
except UnknownEvenFeatureBits:
|
||||
self.logger.info("unknown feature bits")
|
||||
except IncompatibleOrInsaneFeatures as e:
|
||||
self.logger.info(f"unknown or insane feature bits: {e!r}")
|
||||
continue
|
||||
if trusted:
|
||||
added += 1
|
||||
|
@ -346,7 +346,7 @@ class ChannelDB(SqlDB):
|
|||
def add_verified_channel_info(self, msg: dict, *, capacity_sat: int = None) -> None:
|
||||
try:
|
||||
channel_info = ChannelInfo.from_msg(msg)
|
||||
except UnknownEvenFeatureBits:
|
||||
except IncompatibleOrInsaneFeatures:
|
||||
return
|
||||
channel_info = channel_info._replace(capacity_sat=capacity_sat)
|
||||
with self.lock:
|
||||
|
@ -499,7 +499,7 @@ class ChannelDB(SqlDB):
|
|||
for msg_payload in msg_payloads:
|
||||
try:
|
||||
node_info, node_addresses = NodeInfo.from_msg(msg_payload)
|
||||
except UnknownEvenFeatureBits:
|
||||
except IncompatibleOrInsaneFeatures:
|
||||
continue
|
||||
node_id = node_info.node_id
|
||||
# Ignore node if it has no associated channel (DoS protection)
|
||||
|
@ -593,11 +593,17 @@ class ChannelDB(SqlDB):
|
|||
self._recent_peers = sorted_node_ids[:self.NUM_MAX_RECENT_PEERS]
|
||||
c.execute("""SELECT * FROM channel_info""")
|
||||
for short_channel_id, msg in c:
|
||||
try:
|
||||
ci = ChannelInfo.from_raw_msg(msg)
|
||||
except IncompatibleOrInsaneFeatures:
|
||||
continue
|
||||
self._channels[ShortChannelID.normalize(short_channel_id)] = ci
|
||||
c.execute("""SELECT * FROM node_info""")
|
||||
for node_id, msg in c:
|
||||
try:
|
||||
node_info, node_addresses = NodeInfo.from_raw_msg(msg)
|
||||
except IncompatibleOrInsaneFeatures:
|
||||
continue
|
||||
# don't load node_addresses because they dont have timestamps
|
||||
self._nodes[node_id] = node_info
|
||||
c.execute("""SELECT * FROM policy""")
|
||||
|
|
|
@ -170,7 +170,7 @@ def pull_tagged(stream):
|
|||
length = stream.read(5).uint * 32 + stream.read(5).uint
|
||||
return (CHARSET[tag], stream.read(length * 5), stream)
|
||||
|
||||
def lnencode(addr: 'LnAddr', privkey):
|
||||
def lnencode(addr: 'LnAddr', privkey) -> str:
|
||||
if addr.amount:
|
||||
amount = Decimal(str(addr.amount))
|
||||
# We can only send down to millisatoshi.
|
||||
|
|
|
@ -165,7 +165,6 @@ class HandshakeFailed(LightningError): pass
|
|||
class ConnStringFormatError(LightningError): pass
|
||||
class UnknownPaymentHash(LightningError): pass
|
||||
class RemoteMisbehaving(LightningError): pass
|
||||
class UnknownEvenFeatureBits(Exception): pass
|
||||
|
||||
class NotFoundChanAnnouncementForUpdate(Exception): pass
|
||||
|
||||
|
@ -855,7 +854,11 @@ def get_ln_flag_pair_of_bit(flag_bit: int) -> int:
|
|||
return flag_bit - 1
|
||||
|
||||
|
||||
class IncompatibleLightningFeatures(ValueError): pass
|
||||
|
||||
class IncompatibleOrInsaneFeatures(Exception): pass
|
||||
class UnknownEvenFeatureBits(IncompatibleOrInsaneFeatures): pass
|
||||
class IncompatibleLightningFeatures(IncompatibleOrInsaneFeatures): pass
|
||||
|
||||
|
||||
def ln_compare_features(our_features: 'LnFeatures', their_features: int) -> 'LnFeatures':
|
||||
"""Returns negotiated features.
|
||||
|
@ -886,13 +889,17 @@ def ln_compare_features(our_features: 'LnFeatures', their_features: int) -> 'LnF
|
|||
|
||||
|
||||
def validate_features(features: int) -> None:
|
||||
"""Raises UnknownEvenFeatureBits if there is an unimplemented
|
||||
mandatory feature.
|
||||
"""Raises IncompatibleOrInsaneFeatures if
|
||||
- a mandatory feature is listed that we don't recognize, or
|
||||
- the features are inconsistent
|
||||
"""
|
||||
features = LnFeatures(features)
|
||||
enabled_features = list_enabled_bits(features)
|
||||
for fbit in enabled_features:
|
||||
if (1 << fbit) & LN_FEATURES_IMPLEMENTED == 0 and fbit % 2 == 0:
|
||||
raise UnknownEvenFeatureBits(fbit)
|
||||
if not features.validate_transitive_dependecies():
|
||||
raise IncompatibleOrInsaneFeatures("not all transitive dependencies are set")
|
||||
|
||||
|
||||
def derive_payment_secret_from_payment_preimage(payment_preimage: bytes) -> bytes:
|
||||
|
|
|
@ -78,11 +78,11 @@ class TestBolt11(ElectrumTestCase):
|
|||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 514)]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 10 + (1 << 8))]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 10 + (1 << 9))]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 10 + (1 << 11))]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 10 + (1 << 7) + (1 << 11))]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 10 + (1 << 12))]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 10 + (1 << 13))]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 10 + (1 << 14))]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 10 + (1 << 15))]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 10 + (1 << 9) + (1 << 14))]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 10 + (1 << 9) + (1 << 15))]),
|
||||
LnAddr(paymenthash=RHASH, amount=24, tags=[('h', longdescription), ('9', 33282)], payment_secret=b"\x11" * 32),
|
||||
]
|
||||
|
||||
|
@ -128,8 +128,8 @@ class TestBolt11(ElectrumTestCase):
|
|||
lndecode("lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdees9q4pqqqqqqqqqqqqqqqqqqszk3ed62snp73037h4py4gry05eltlp0uezm2w9ajnerhmxzhzhsu40g9mgyx5v3ad4aqwkmvyftzk4k9zenz90mhjcy9hcevc7r3lx2sphzfxz7")
|
||||
|
||||
def test_payment_secret(self):
|
||||
lnaddr = lndecode("lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqpqqq4u9s93jtgysm3mrwll70zr697y3mf902hvxwej0v7c62rsltw83ng0pu8w3j230sluc5gxkdmm9dvpy9y6ggtjd2w544mzdrcs42t7sqdkcy8h")
|
||||
self.assertEqual((1 << 15) + (1 << 99) , lnaddr.get_tag('9'))
|
||||
lnaddr = lndecode("lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygsdq5vdhkven9v5sxyetpdees9q5sqqqqqqqqqqqqqqqpqsqvvh7ut50r00p3pg34ea68k7zfw64f8yx9jcdk35lh5ft8qdr8g4r0xzsdcrmcy9hex8un8d8yraewvhqc9l0sh8l0e0yvmtxde2z0hgpzsje5l")
|
||||
self.assertEqual((1 << 9) + (1 << 15) + (1 << 99), lnaddr.get_tag('9'))
|
||||
self.assertEqual(b"\x11" * 32, lnaddr.payment_secret)
|
||||
|
||||
def test_derive_payment_secret_from_payment_preimage(self):
|
||||
|
|
Loading…
Add table
Reference in a new issue