Browse Source

clean up local/global features

regtest_lnd
SomberNight 6 years ago
parent
commit
03dc812087
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 23
      electrum/lnbase.py
  2. 6
      electrum/lnrouter.py
  3. 43
      electrum/lnutil.py

23
electrum/lnbase.py

@ -17,6 +17,7 @@ from typing import List
import cryptography.hazmat.primitives.ciphers.aead as AEAD import cryptography.hazmat.primitives.ciphers.aead as AEAD
import aiorpcx import aiorpcx
from .util import list_enabled_bits
from . import bitcoin from . import bitcoin
from . import ecc from . import ecc
from .ecc import sig_string_from_r_and_s, get_r_and_s_from_sig_string from .ecc import sig_string_from_r_and_s, get_r_and_s_from_sig_string
@ -30,8 +31,9 @@ from .lnhtlc import HTLCStateMachine, RevokeAndAck
from .lnutil import (Outpoint, ChannelConfig, LocalState, from .lnutil import (Outpoint, ChannelConfig, LocalState,
RemoteState, OnlyPubkeyKeypair, ChannelConstraints, RevocationStore, RemoteState, OnlyPubkeyKeypair, ChannelConstraints, RevocationStore,
funding_output_script, get_ecdh, get_per_commitment_secret_from_seed, funding_output_script, get_ecdh, get_per_commitment_secret_from_seed,
secret_to_pubkey, LNPeerAddr, PaymentFailure, secret_to_pubkey, LNPeerAddr, PaymentFailure, LnLocalFeatures,
LOCAL, REMOTE, HTLCOwner, generate_keypair, LnKeyFamily) LOCAL, REMOTE, HTLCOwner, generate_keypair, LnKeyFamily,
get_ln_flag_pair_of_bit)
from .lnrouter import NotFoundChanAnnouncementForUpdate, RouteEdge from .lnrouter import NotFoundChanAnnouncementForUpdate, RouteEdge
@ -290,7 +292,10 @@ class Peer(PrintError):
self.announcement_signatures = defaultdict(asyncio.Queue) self.announcement_signatures = defaultdict(asyncio.Queue)
self.closing_signed = defaultdict(asyncio.Queue) self.closing_signed = defaultdict(asyncio.Queue)
self.payment_preimages = defaultdict(asyncio.Queue) self.payment_preimages = defaultdict(asyncio.Queue)
self.localfeatures = (0x08 if request_initial_sync else 0) self.localfeatures = LnLocalFeatures(0)
if request_initial_sync:
self.localfeatures |= LnLocalFeatures.INITIAL_ROUTING_SYNC
self.localfeatures |= LnLocalFeatures.OPTION_DATA_LOSS_PROTECT_OPT
self.invoices = lnworker.invoices self.invoices = lnworker.invoices
self.attempted_route = {} self.attempted_route = {}
@ -442,7 +447,17 @@ class Peer(PrintError):
self.network.trigger_callback('ln_status') self.network.trigger_callback('ln_status')
def on_init(self, payload): def on_init(self, payload):
pass # if they required some even flag we don't have, they will close themselves
# but if we require an even flag they don't have, we close
our_flags = set(list_enabled_bits(self.localfeatures))
their_flags = set(list_enabled_bits(int.from_bytes(payload['localfeatures'], byteorder="big")))
for flag in our_flags:
if flag not in their_flags and get_ln_flag_pair_of_bit(flag) not in their_flags:
# they don't have this feature we wanted :(
if flag % 2 == 0: # even flags are compulsory
raise LightningPeerConnectionClosed("remote does not have even flag {}"
.format(str(LnLocalFeatures(1 << flag))))
self.localfeatures ^= 1 << flag # disable flag
def on_channel_update(self, payload): def on_channel_update(self, payload):
try: try:

6
electrum/lnrouter.py

@ -39,7 +39,7 @@ from .storage import JsonDB
from .lnchannelverifier import LNChannelVerifier, verify_sig_for_channel_update from .lnchannelverifier import LNChannelVerifier, verify_sig_for_channel_update
from .crypto import Hash from .crypto import Hash
from . import ecc from . import ecc
from .lnutil import LN_GLOBAL_FEATURE_BITS, LNPeerAddr from .lnutil import LN_GLOBAL_FEATURES_KNOWN_SET, LNPeerAddr
class UnknownEvenFeatureBits(Exception): pass class UnknownEvenFeatureBits(Exception): pass
@ -55,7 +55,7 @@ class ChannelInfo(PrintError):
self.features = channel_announcement_payload['features'] self.features = channel_announcement_payload['features']
enabled_features = list_enabled_bits(int.from_bytes(self.features, "big")) enabled_features = list_enabled_bits(int.from_bytes(self.features, "big"))
for fbit in enabled_features: for fbit in enabled_features:
if fbit not in LN_GLOBAL_FEATURE_BITS and fbit % 2 == 0: if (1 << fbit) not in LN_GLOBAL_FEATURES_KNOWN_SET and fbit % 2 == 0:
raise UnknownEvenFeatureBits() raise UnknownEvenFeatureBits()
self.channel_id = channel_announcement_payload['short_channel_id'] self.channel_id = channel_announcement_payload['short_channel_id']
@ -191,7 +191,7 @@ class NodeInfo(PrintError):
self.features = node_announcement_payload['features'] self.features = node_announcement_payload['features']
enabled_features = list_enabled_bits(int.from_bytes(self.features, "big")) enabled_features = list_enabled_bits(int.from_bytes(self.features, "big"))
for fbit in enabled_features: for fbit in enabled_features:
if fbit not in LN_GLOBAL_FEATURE_BITS and fbit % 2 == 0: if (1 << fbit) not in LN_GLOBAL_FEATURES_KNOWN_SET and fbit % 2 == 0:
raise UnknownEvenFeatureBits() raise UnknownEvenFeatureBits()
if not addresses_already_parsed: if not addresses_already_parsed:
self.addresses = self.parse_addresses_field(node_announcement_payload['addresses']) self.addresses = self.parse_addresses_field(node_announcement_payload['addresses'])

43
electrum/lnutil.py

@ -426,19 +426,36 @@ def get_ecdh(priv: bytes, pub: bytes) -> bytes:
return sha256(pt.get_public_key_bytes()) return sha256(pt.get_public_key_bytes())
LN_LOCAL_FEATURE_BITS = { class LnLocalFeatures(IntFlag):
0: 'option_data_loss_protect_req', OPTION_DATA_LOSS_PROTECT_REQ = 1 << 0
1: 'option_data_loss_protect_opt', OPTION_DATA_LOSS_PROTECT_OPT = 1 << 1
3: 'initial_routing_sync', INITIAL_ROUTING_SYNC = 1 << 3
4: 'option_upfront_shutdown_script_req', OPTION_UPFRONT_SHUTDOWN_SCRIPT_REQ = 1 << 4
5: 'option_upfront_shutdown_script_opt', OPTION_UPFRONT_SHUTDOWN_SCRIPT_OPT = 1 << 5
6: 'gossip_queries_req', GOSSIP_QUERIES_REQ = 1 << 6
7: 'gossip_queries_opt', GOSSIP_QUERIES_OPT = 1 << 7
}
LN_LOCAL_FEATURE_BITS_INV = inv_dict(LN_LOCAL_FEATURE_BITS) # note that these are powers of two, not the bits themselves
LN_LOCAL_FEATURES_KNOWN_SET = set(LnLocalFeatures)
LN_GLOBAL_FEATURE_BITS = {}
LN_GLOBAL_FEATURE_BITS_INV = inv_dict(LN_GLOBAL_FEATURE_BITS)
def get_ln_flag_pair_of_bit(flag_bit: int):
"""Ln Feature flags are assigned in pairs, one even, one odd. See BOLT-09.
Return the other flag from the pair.
e.g. 6 -> 7
e.g. 7 -> 6
"""
if flag_bit % 2 == 0:
return flag_bit + 1
else:
return flag_bit - 1
class LnGlobalFeatures(IntFlag):
pass
# note that these are powers of two, not the bits themselves
LN_GLOBAL_FEATURES_KNOWN_SET = set(LnGlobalFeatures)
class LNPeerAddr(namedtuple('LNPeerAddr', ['host', 'port', 'pubkey'])): class LNPeerAddr(namedtuple('LNPeerAddr', ['host', 'port', 'pubkey'])):

Loading…
Cancel
Save