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 aiorpcx
from .util import list_enabled_bits
from . import bitcoin
from . import ecc
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,
RemoteState, OnlyPubkeyKeypair, ChannelConstraints, RevocationStore,
funding_output_script, get_ecdh, get_per_commitment_secret_from_seed,
secret_to_pubkey, LNPeerAddr, PaymentFailure,
LOCAL, REMOTE, HTLCOwner, generate_keypair, LnKeyFamily)
secret_to_pubkey, LNPeerAddr, PaymentFailure, LnLocalFeatures,
LOCAL, REMOTE, HTLCOwner, generate_keypair, LnKeyFamily,
get_ln_flag_pair_of_bit)
from .lnrouter import NotFoundChanAnnouncementForUpdate, RouteEdge
@ -290,7 +292,10 @@ class Peer(PrintError):
self.announcement_signatures = defaultdict(asyncio.Queue)
self.closing_signed = 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.attempted_route = {}
@ -442,7 +447,17 @@ class Peer(PrintError):
self.network.trigger_callback('ln_status')
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):
try:

6
electrum/lnrouter.py

@ -39,7 +39,7 @@ from .storage import JsonDB
from .lnchannelverifier import LNChannelVerifier, verify_sig_for_channel_update
from .crypto import Hash
from . import ecc
from .lnutil import LN_GLOBAL_FEATURE_BITS, LNPeerAddr
from .lnutil import LN_GLOBAL_FEATURES_KNOWN_SET, LNPeerAddr
class UnknownEvenFeatureBits(Exception): pass
@ -55,7 +55,7 @@ class ChannelInfo(PrintError):
self.features = channel_announcement_payload['features']
enabled_features = list_enabled_bits(int.from_bytes(self.features, "big"))
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()
self.channel_id = channel_announcement_payload['short_channel_id']
@ -191,7 +191,7 @@ class NodeInfo(PrintError):
self.features = node_announcement_payload['features']
enabled_features = list_enabled_bits(int.from_bytes(self.features, "big"))
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()
if not addresses_already_parsed:
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())
LN_LOCAL_FEATURE_BITS = {
0: 'option_data_loss_protect_req',
1: 'option_data_loss_protect_opt',
3: 'initial_routing_sync',
4: 'option_upfront_shutdown_script_req',
5: 'option_upfront_shutdown_script_opt',
6: 'gossip_queries_req',
7: 'gossip_queries_opt',
}
LN_LOCAL_FEATURE_BITS_INV = inv_dict(LN_LOCAL_FEATURE_BITS)
LN_GLOBAL_FEATURE_BITS = {}
LN_GLOBAL_FEATURE_BITS_INV = inv_dict(LN_GLOBAL_FEATURE_BITS)
class LnLocalFeatures(IntFlag):
OPTION_DATA_LOSS_PROTECT_REQ = 1 << 0
OPTION_DATA_LOSS_PROTECT_OPT = 1 << 1
INITIAL_ROUTING_SYNC = 1 << 3
OPTION_UPFRONT_SHUTDOWN_SCRIPT_REQ = 1 << 4
OPTION_UPFRONT_SHUTDOWN_SCRIPT_OPT = 1 << 5
GOSSIP_QUERIES_REQ = 1 << 6
GOSSIP_QUERIES_OPT = 1 << 7
# note that these are powers of two, not the bits themselves
LN_LOCAL_FEATURES_KNOWN_SET = set(LnLocalFeatures)
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'])):

Loading…
Cancel
Save