Browse Source

Save channel seed in localconfig

hard-fail-on-bad-server-string
ThomasV 5 years ago
parent
commit
0ea21c59d2
  1. 25
      electrum/lnpeer.py
  2. 18
      electrum/lnutil.py
  3. 1
      electrum/tests/test_lnchannel.py
  4. 11
      electrum/wallet_db.py

25
electrum/lnpeer.py

@ -20,7 +20,6 @@ import aiorpcx
from .crypto import sha256, sha256d from .crypto import sha256, sha256d
from . import bitcoin from . import bitcoin
from .bip32 import BIP32Node
from . import ecc from . import ecc
from .ecc import sig_string_from_r_and_s, get_r_and_s_from_sig_string, der_sig_from_sig_string from .ecc import sig_string_from_r_and_s, get_r_and_s_from_sig_string, der_sig_from_sig_string
from . import constants from . import constants
@ -484,38 +483,32 @@ class Peer(Logger):
return bool(self.features & LnFeatures.OPTION_STATIC_REMOTEKEY_OPT) return bool(self.features & LnFeatures.OPTION_STATIC_REMOTEKEY_OPT)
def make_local_config(self, funding_sat: int, push_msat: int, initiator: HTLCOwner) -> LocalConfig: def make_local_config(self, funding_sat: int, push_msat: int, initiator: HTLCOwner) -> LocalConfig:
# key derivation
seed = os.urandom(32)
node = BIP32Node.from_rootseed(seed, xtype='standard')
keypair_generator = lambda family: generate_keypair(node, family)
random_seed = os.urandom(32)
if initiator == LOCAL: if initiator == LOCAL:
initial_msat = funding_sat * 1000 - push_msat initial_msat = funding_sat * 1000 - push_msat
else: else:
initial_msat = push_msat initial_msat = push_msat
if self.is_static_remotekey(): if self.is_static_remotekey():
# Note: in the future, if a CSV delay is added,
# we will want to derive that key
wallet = self.lnworker.wallet wallet = self.lnworker.wallet
assert wallet.txin_type == 'p2wpkh' assert wallet.txin_type == 'p2wpkh'
addr = wallet.get_unused_address() addr = wallet.get_unused_address()
static_key = wallet.get_public_key(addr) # just a pubkey static_remotekey = bfh(wallet.get_public_key(addr))
payment_basepoint = OnlyPubkeyKeypair(bfh(static_key))
else: else:
payment_basepoint = keypair_generator(LnKeyFamily.PAYMENT_BASE) static_remotekey = None
local_config=LocalConfig( local_config = LocalConfig.from_seed(
payment_basepoint=payment_basepoint, seed=random_seed,
multisig_key=keypair_generator(LnKeyFamily.MULTISIG), static_remotekey=static_remotekey,
htlc_basepoint=keypair_generator(LnKeyFamily.HTLC_BASE),
delayed_basepoint=keypair_generator(LnKeyFamily.DELAY_BASE),
revocation_basepoint=keypair_generator(LnKeyFamily.REVOCATION_BASE),
to_self_delay=DEFAULT_TO_SELF_DELAY, to_self_delay=DEFAULT_TO_SELF_DELAY,
dust_limit_sat=546, dust_limit_sat=546,
max_htlc_value_in_flight_msat=funding_sat * 1000, max_htlc_value_in_flight_msat=funding_sat * 1000,
max_accepted_htlcs=5, max_accepted_htlcs=5,
initial_msat=initial_msat, initial_msat=initial_msat,
reserve_sat=546, reserve_sat=546,
per_commitment_secret_seed=keypair_generator(LnKeyFamily.REVOCATION_ROOT).privkey,
funding_locked_received=False, funding_locked_received=False,
was_announced=False, was_announced=False,
current_commitment_signature=None, current_commitment_signature=None,

18
electrum/lnutil.py

@ -77,11 +77,27 @@ class Config(StoredObject):
@attr.s @attr.s
class LocalConfig(Config): class LocalConfig(Config):
per_commitment_secret_seed = attr.ib(type=bytes, converter=hex_to_bytes) seed = attr.ib(type=bytes, converter=hex_to_bytes)
funding_locked_received = attr.ib(type=bool) funding_locked_received = attr.ib(type=bool)
was_announced = attr.ib(type=bool) was_announced = attr.ib(type=bool)
current_commitment_signature = attr.ib(type=bytes, converter=hex_to_bytes) current_commitment_signature = attr.ib(type=bytes, converter=hex_to_bytes)
current_htlc_signatures = attr.ib(type=bytes, converter=hex_to_bytes) current_htlc_signatures = attr.ib(type=bytes, converter=hex_to_bytes)
per_commitment_secret_seed = attr.ib(type=bytes, converter=hex_to_bytes)
@classmethod
def from_seed(self, **kwargs):
seed = kwargs['seed']
static_remotekey = kwargs.pop('static_remotekey')
node = BIP32Node.from_rootseed(seed, xtype='standard')
keypair_generator = lambda family: generate_keypair(node, family)
kwargs['per_commitment_secret_seed'] = keypair_generator(LnKeyFamily.REVOCATION_ROOT).privkey
kwargs['multisig_key'] = keypair_generator(LnKeyFamily.MULTISIG)
kwargs['htlc_basepoint'] = keypair_generator(LnKeyFamily.HTLC_BASE)
kwargs['delayed_basepoint'] = keypair_generator(LnKeyFamily.DELAY_BASE)
kwargs['revocation_basepoint'] = keypair_generator(LnKeyFamily.REVOCATION_BASE)
kwargs['payment_basepoint'] = OnlyPubkeyKeypair(static_remotekey) if static_remotekey else keypair_generator(LnKeyFamily.PAYMENT_BASE)
return LocalConfig(**kwargs)
@attr.s @attr.s
class RemoteConfig(Config): class RemoteConfig(Config):

1
electrum/tests/test_lnchannel.py

@ -70,6 +70,7 @@ def create_channel_state(funding_txid, funding_index, funding_sat, is_initiator,
current_per_commitment_point=cur, current_per_commitment_point=cur,
), ),
"local_config":lnpeer.LocalConfig( "local_config":lnpeer.LocalConfig(
seed = None,
payment_basepoint=privkeys[0], payment_basepoint=privkeys[0],
multisig_key=privkeys[1], multisig_key=privkeys[1],
htlc_basepoint=privkeys[2], htlc_basepoint=privkeys[2],

11
electrum/wallet_db.py

@ -50,7 +50,7 @@ if TYPE_CHECKING:
OLD_SEED_VERSION = 4 # electrum versions < 2.0 OLD_SEED_VERSION = 4 # electrum versions < 2.0
NEW_SEED_VERSION = 11 # electrum versions >= 2.0 NEW_SEED_VERSION = 11 # electrum versions >= 2.0
FINAL_SEED_VERSION = 27 # electrum >= 2.7 will set this to prevent FINAL_SEED_VERSION = 28 # electrum >= 2.7 will set this to prevent
# old versions from overwriting new format # old versions from overwriting new format
@ -173,6 +173,7 @@ class WalletDB(JsonDB):
self._convert_version_25() self._convert_version_25()
self._convert_version_26() self._convert_version_26()
self._convert_version_27() self._convert_version_27()
self._convert_version_28()
self.put('seed_version', FINAL_SEED_VERSION) # just to be sure self.put('seed_version', FINAL_SEED_VERSION) # just to be sure
self._after_upgrade_tasks() self._after_upgrade_tasks()
@ -596,6 +597,14 @@ class WalletDB(JsonDB):
c['local_config']['htlc_minimum_msat'] = 1 c['local_config']['htlc_minimum_msat'] = 1
self.data['seed_version'] = 27 self.data['seed_version'] = 27
def _convert_version_28(self):
if not self._is_upgrade_method_needed(27, 27):
return
channels = self.data.get('channels', {})
for channel_id, c in channels.items():
c['local_config']['seed'] = None
self.data['seed_version'] = 28
def _convert_imported(self): def _convert_imported(self):
if not self._is_upgrade_method_needed(0, 13): if not self._is_upgrade_method_needed(0, 13):
return return

Loading…
Cancel
Save