Browse Source

lnbase: organize channel data

dependabot/pip/contrib/deterministic-build/ecdsa-0.13.3
Janus 7 years ago
committed by ThomasV
parent
commit
39dcc24133
  1. 250
      lib/lnbase.py
  2. 5
      lib/tests/test_lnbase_online.py

250
lib/lnbase.py

@ -32,14 +32,6 @@ from .util import PrintError, bh2u, print_error, bfh, profiler
from .transaction import opcodes, Transaction
from collections import namedtuple, defaultdict
LocalCtxArgs = namedtuple("LocalCtxArgs",
["ctn",
"funding_pubkey", "remote_funding_pubkey", "remotepubkey",
"base_point", "remote_payment_basepoint",
"remote_revocation_pubkey", "local_delayedpubkey", "to_self_delay",
"funding_txid", "funding_index", "funding_satoshis",
"local_amount", "remote_amount", "dust_limit_satoshis", "local_feerate",
"commitment_owner"])
# hardcoded nodes
node_list = [
@ -289,6 +281,17 @@ def create_ephemeral_key(privkey):
pub = privkey_to_pubkey(privkey)
return (privkey[:32], pub)
Keypair = namedtuple("Keypair", ["pubkey", "privkey"])
Outpoint = namedtuple("Outpoint", ["txid", "output_index"])
ChannelConfig = namedtuple("ChannelConfig", [
"payment_key", "multisig_key", "htlc_key", "delayed_key", "revocation_key",
"to_self_delay", "dust_limit_sat", "max_htlc_value_in_flight_msat", "max_accepted_htlcs"])
OnlyPubkeyKeypair = namedtuple("OnlyPubkeyKeypair", ["pubkey"])
RemoteState = namedtuple("RemoteState", ["ctn", "next_per_commitment_point", "amount_sat"])
LocalState = namedtuple("LocalState", ["ctn", "per_commitment_secret_seed", "amount_sat"])
ChannelConstraints = namedtuple("ChannelConstraints", ["feerate", "capacity", "is_initiator"])
OpenChannel = namedtuple("OpenChannel", ["channel_id", "funding_outpoint", "local_config", "remote_config", "remote_state", "local_state", "constraints"])
class KeypairGenerator:
def __init__(self, seed):
self.xprv, xpub = bitcoin.bip32_root(seed, "p2wpkh")
@ -297,7 +300,7 @@ class KeypairGenerator:
_, _, _, _, child_c, child_cK = bitcoin.deserialize_xpub(childxpub)
_, _, _, _, _, k = bitcoin.deserialize_xprv(childxprv)
assert len(k) == 32
return child_cK, k
return Keypair(pubkey=child_cK, privkey=k)
def aiosafe(f):
async def f2(*args, **kwargs):
@ -446,12 +449,12 @@ def make_received_htlc(revocation_pubkey, remote_htlcpubkey, local_htlcpubkey, p
+ bytes([opcodes.OP_CLTV, opcodes.OP_DROP, opcodes.OP_CHECKSIG, opcodes.OP_ENDIF, opcodes.OP_ENDIF])
def make_commitment(ctn, local_funding_pubkey, remote_funding_pubkey, remotepubkey,
def make_commitment(ctn, local_funding_pubkey, remote_funding_pubkey, remote_payment_pubkey,
payment_basepoint, remote_payment_basepoint,
revocation_pubkey, delayed_pubkey, to_self_delay,
funding_txid, funding_pos, funding_satoshis,
funding_txid, funding_pos, funding_sat,
local_amount, remote_amount,
dust_limit_satoshis, local_feerate, for_us, htlcs):
dust_limit_sat, local_feerate, for_us, htlcs):
pubkeys = sorted([bh2u(local_funding_pubkey), bh2u(remote_funding_pubkey)])
obs = get_obscured_ctn(ctn, payment_basepoint, remote_payment_basepoint)
@ -466,7 +469,7 @@ def make_commitment(ctn, local_funding_pubkey, remote_funding_pubkey, remotepubk
'num_sig': 2,
'prevout_n': funding_pos,
'prevout_hash': funding_txid,
'value': funding_satoshis,
'value': funding_sat,
'coinbase': False,
'sequence':sequence
}]
@ -474,7 +477,7 @@ def make_commitment(ctn, local_funding_pubkey, remote_funding_pubkey, remotepubk
local_script = bytes([opcodes.OP_IF]) + bfh(push_script(bh2u(revocation_pubkey))) + bytes([opcodes.OP_ELSE]) + add_number_to_script(to_self_delay) \
+ bytes([opcodes.OP_CSV, opcodes.OP_DROP]) + bfh(push_script(bh2u(delayed_pubkey))) + bytes([opcodes.OP_ENDIF, opcodes.OP_CHECKSIG])
local_address = bitcoin.redeem_script_to_address('p2wsh', bh2u(local_script))
remote_address = bitcoin.pubkey_to_address('p2wpkh', bh2u(remotepubkey))
remote_address = bitcoin.pubkey_to_address('p2wpkh', bh2u(remote_payment_pubkey))
# TODO trim htlc outputs here while also considering 2nd stage htlc transactions
fee = local_feerate * overall_weight(len(htlcs)) // 1000 # TODO incorrect if anything is trimmed
to_local = (bitcoin.TYPE_ADDRESS, local_address, local_amount - (fee if for_us else 0))
@ -483,7 +486,8 @@ def make_commitment(ctn, local_funding_pubkey, remote_funding_pubkey, remotepubk
for script, msat_amount in htlcs:
c_outputs += [(bitcoin.TYPE_ADDRESS, bitcoin.redeem_script_to_address('p2wsh', bh2u(script)), msat_amount // 1000)]
# trim outputs
c_outputs = list(filter(lambda x:x[2]>= dust_limit_satoshis, c_outputs))
c_outputs = list(filter(lambda x:x[2]>= dust_limit_sat, c_outputs))
assert sum(x[2] for x in c_outputs) <= funding_sat
# create commitment tx
tx = Transaction.from_io(c_inputs, c_outputs, locktime=locktime, version=2)
@ -687,7 +691,7 @@ class Peer(PrintError):
self.channel_db.on_channel_announcement(payload)
#def open_channel(self, funding_sat, push_msat):
# self.send_message(gen_msg('open_channel', funding_satoshis=funding_sat, push_msat=push_msat))
# self.send_message(gen_msg('open_channel', funding_sat=funding_sat, push_msat=push_msat))
@aiosafe
async def main_loop(self):
@ -710,7 +714,7 @@ class Peer(PrintError):
self.writer.close()
@aiosafe
async def channel_establishment_flow(self, wallet, config, funding_satoshis, push_msat, temp_channel_id, keypair_generator=None):
async def channel_establishment_flow(self, wallet, config, funding_sat, push_msat, temp_channel_id, keypair_generator=None):
await self.initialized
if keypair_generator is None:
@ -725,40 +729,41 @@ class Peer(PrintError):
keyfamilyrevocationroot = 5
keyfamilynodekey = 6 # TODO currently unused
funding_pubkey, funding_privkey = keypair_generator.get(keyfamilymultisig, 0)
revocation_basepoint, _ = keypair_generator.get(keyfamilyrevocationbase, 0)
htlc_basepoint, htlc_privkey = keypair_generator.get(keyfamilyhtlcbase, 0)
delayed_payment_basepoint, delayed_privkey = keypair_generator.get(keyfamilydelaybase, 0)
base_point, _ = keypair_generator.get(keyfamilypaymentbase, 0)
funding_key = keypair_generator.get(keyfamilymultisig, 0)
revocation_key = keypair_generator.get(keyfamilyrevocationbase, 0)
htlc_key = keypair_generator.get(keyfamilyhtlcbase, 0)
delayed_key = keypair_generator.get(keyfamilydelaybase, 0)
base_point = keypair_generator.get(keyfamilypaymentbase, 0)
per_commitment_secret_seed = 0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100.to_bytes(32, "big")
per_commitment_secret_index = 2**48 - 1
# amounts
local_feerate = 20000
dust_limit_satoshis = 10
to_self_delay = 144
ctn = 0
dust_limit_sat = 10
#
per_commitment_secret_first = get_per_commitment_secret_from_seed(per_commitment_secret_seed, per_commitment_secret_index)
per_commitment_point_first = secret_to_pubkey(int.from_bytes(
per_commitment_secret_first,
byteorder="big"))
local_max_htlc_value_in_flight_msat = 500000 * 1000
local_max_accepted_htlcs = 5
msg = gen_msg(
"open_channel",
temporary_channel_id=temp_channel_id,
chain_hash=bytes.fromhex(rev_hex(constants.net.GENESIS)),
funding_satoshis=funding_satoshis,
funding_satoshis=funding_sat,
push_msat=push_msat,
dust_limit_satoshis=dust_limit_satoshis,
dust_limit_satoshis=dust_limit_sat,
feerate_per_kw=local_feerate,
max_accepted_htlcs=5,
funding_pubkey=funding_pubkey,
revocation_basepoint=revocation_basepoint,
htlc_basepoint=htlc_basepoint,
payment_basepoint=base_point,
delayed_payment_basepoint=delayed_payment_basepoint,
max_accepted_htlcs=local_max_accepted_htlcs,
funding_pubkey=funding_key.pubkey,
revocation_basepoint=revocation_key.pubkey,
htlc_basepoint=htlc_key.pubkey,
payment_basepoint=base_point.pubkey,
delayed_payment_basepoint=delayed_key.pubkey,
first_per_commitment_point=per_commitment_point_first,
to_self_delay=to_self_delay,
max_htlc_value_in_flight_msat=500000 * 1000
max_htlc_value_in_flight_msat=local_max_htlc_value_in_flight_msat
)
#self.channel_accepted[temp_channel_id] = asyncio.Future()
self.send_message(msg)
@ -766,10 +771,11 @@ class Peer(PrintError):
payload = await self.channel_accepted[temp_channel_id]
finally:
del self.channel_accepted[temp_channel_id]
remote_max_accepted_htlcs = payload["max_accepted_htlcs"]
remote_per_commitment_point = payload['first_per_commitment_point']
remote_funding_pubkey = payload["funding_pubkey"]
remote_delay = int.from_bytes(payload['to_self_delay'], byteorder="big")
remote_dust_limit_satoshis = int.from_bytes(payload['dust_limit_satoshis'], byteorder="big")
remote_dust_limit_sat = int.from_bytes(payload['dust_limit_satoshis'], byteorder="big")
remote_revocation_basepoint = payload['revocation_basepoint']
remote_payment_basepoint = payload['payment_basepoint']
remote_delayed_payment_basepoint = payload['delayed_payment_basepoint']
@ -777,44 +783,44 @@ class Peer(PrintError):
remote_htlc_minimum_msat = int.from_bytes(payload['htlc_minimum_msat'], "big")
remote_max_htlc_value_in_flight_msat = int.from_bytes(payload['max_htlc_value_in_flight_msat'], "big")
funding_txn_minimum_depth = int.from_bytes(payload['minimum_depth'], byteorder="big")
print('remote dust limit', remote_dust_limit_satoshis)
assert remote_dust_limit_satoshis < 600
print('remote dust limit', remote_dust_limit_sat)
assert remote_dust_limit_sat < 600
assert remote_htlc_minimum_msat < 600 * 1000
assert remote_max_htlc_value_in_flight_msat >= 500 * 1000 * 1000, remote_max_htlc_value_in_flight_msat
self.print_error('remote delay', remote_delay)
self.print_error('funding_txn_minimum_depth', funding_txn_minimum_depth)
# create funding tx
pubkeys = sorted([bh2u(funding_pubkey), bh2u(remote_funding_pubkey)])
pubkeys = sorted([bh2u(funding_key.pubkey), bh2u(remote_funding_pubkey)])
redeem_script = transaction.multisig_script(pubkeys, 2)
funding_address = bitcoin.redeem_script_to_address('p2wsh', redeem_script)
funding_output = (bitcoin.TYPE_ADDRESS, funding_address, funding_satoshis)
funding_output = (bitcoin.TYPE_ADDRESS, funding_address, funding_sat)
funding_tx = wallet.mktx([funding_output], None, config, 1000)
funding_txid = funding_tx.txid()
funding_index = funding_tx.outputs().index(funding_output)
# derive keys
localpubkey = derive_pubkey(base_point, remote_per_commitment_point) #local_payment_pubkey
#localprivkey = derive_privkey(base_secret, remote_per_commitment_point)
remotepubkey = derive_pubkey(remote_payment_basepoint, per_commitment_point_first)
revocation_pubkey = derive_blinded_pubkey(revocation_basepoint, remote_per_commitment_point)
local_payment_pubkey = derive_pubkey(base_point.pubkey, remote_per_commitment_point)
#local_payment_privkey = derive_privkey(base_secret, remote_per_commitment_point)
remote_payment_pubkey = derive_pubkey(remote_payment_basepoint, per_commitment_point_first)
revocation_pubkey = derive_blinded_pubkey(revocation_key.pubkey, remote_per_commitment_point)
remote_revocation_pubkey = derive_blinded_pubkey(remote_revocation_basepoint, per_commitment_point_first)
local_delayedpubkey = derive_pubkey(delayed_payment_basepoint, per_commitment_point_first)
local_delayedpubkey = derive_pubkey(delayed_key.pubkey, per_commitment_point_first)
remote_delayedpubkey = derive_pubkey(remote_delayed_payment_basepoint, remote_per_commitment_point)
# compute amounts
htlcs = []
to_local_msat = funding_satoshis*1000 - push_msat
to_local_msat = funding_sat*1000 - push_msat
to_remote_msat = push_msat
local_amount = to_local_msat // 1000
remote_amount = to_remote_msat // 1000
# remote commitment transaction
remote_ctx = make_commitment(
ctn,
remote_funding_pubkey, funding_pubkey, localpubkey,
base_point, remote_payment_basepoint,
0,
remote_funding_pubkey, funding_key.pubkey, local_payment_pubkey,
base_point.pubkey, remote_payment_basepoint,
revocation_pubkey, remote_delayedpubkey, remote_delay,
funding_txid, funding_index, funding_satoshis,
remote_amount, local_amount, remote_dust_limit_satoshis, local_feerate, False, htlcs=[])
remote_ctx.sign({bh2u(funding_pubkey): (funding_privkey, True)})
sig_index = pubkeys.index(bh2u(funding_pubkey))
funding_txid, funding_index, funding_sat,
remote_amount, local_amount, remote_dust_limit_sat, local_feerate, False, htlcs=[])
remote_ctx.sign({bh2u(funding_key.pubkey): (funding_key.privkey, True)})
sig_index = pubkeys.index(bh2u(funding_key.pubkey))
sig = bytes.fromhex(remote_ctx.inputs()[0]["signatures"][sig_index])
r, s = sigdecode_der(sig[:-1], SECP256k1.generator.order())
sig_64 = sigencode_string_canonize(r, s, SECP256k1.generator.order())
@ -829,14 +835,13 @@ class Peer(PrintError):
self.print_error('received funding_signed')
remote_sig = payload['signature']
# verify remote signature
local_ctx_args = LocalCtxArgs(
ctn,
funding_pubkey, remote_funding_pubkey, remotepubkey,
base_point, remote_payment_basepoint,
local_ctx = make_commitment(
0,
funding_key.pubkey, remote_funding_pubkey, remote_payment_pubkey,
base_point.pubkey, remote_payment_basepoint,
remote_revocation_pubkey, local_delayedpubkey, to_self_delay,
funding_txid, funding_index, funding_satoshis,
local_amount, remote_amount, dust_limit_satoshis, local_feerate, True)
local_ctx = make_commitment(*local_ctx_args, htlcs=[])
funding_txid, funding_index, funding_sat,
local_amount, remote_amount, dust_limit_sat, local_feerate, True, htlcs=[])
pre_hash = bitcoin.Hash(bfh(local_ctx.serialize_preimage(0)))
if not bitcoin.verify_signature(remote_funding_pubkey, remote_sig, pre_hash):
raise Exception('verifying remote signature failed.')
@ -876,18 +881,68 @@ class Peer(PrintError):
del self.remote_funding_locked[channel_id]
self.print_error('Done waiting for remote_funding_locked', remote_funding_locked_msg)
#self.commitment_signed[channel_id] = asyncio.Future()
return channel_id, per_commitment_secret_seed, local_ctx_args, remote_funding_pubkey, remote_funding_locked_msg, remote_revocation_basepoint, remote_htlc_basepoint, htlc_basepoint, delayed_payment_basepoint, revocation_basepoint, remote_delayed_payment_basepoint, remote_delay, remote_dust_limit_satoshis, funding_privkey, htlc_privkey
async def receive_commitment_revoke_ack(self, channel_id, local_per_commitment_secret_seed, local_last_pcs_index, local_ctx_args, expected_received_sat, remote_funding_pubkey, local_next_commitment_number, remote_next_commitment_point, remote_revocation_basepoint, remote_htlc_basepoint, local_htlc_basepoint, delayed_payment_basepoint, revocation_basepoint, remote_delayed_payment_basepoint, remote_delay, remote_dust_limit_satoshis, funding_privkey, payment_preimage, htlc_privkey):
return OpenChannel(
channel_id=channel_id,
funding_outpoint=Outpoint(funding_txid, funding_index),
local_config=ChannelConfig(
payment_key=base_point,
multisig_key=funding_key,
htlc_key=htlc_key,
delayed_key=delayed_key,
revocation_key=revocation_key,
to_self_delay=to_self_delay,
dust_limit_sat=dust_limit_sat,
max_htlc_value_in_flight_msat=local_max_htlc_value_in_flight_msat,
max_accepted_htlcs=local_max_accepted_htlcs
),
remote_config=ChannelConfig(
payment_key=OnlyPubkeyKeypair(remote_payment_basepoint),
multisig_key=OnlyPubkeyKeypair(remote_funding_pubkey),
htlc_key=OnlyPubkeyKeypair(remote_htlc_basepoint),
delayed_key=OnlyPubkeyKeypair(remote_delayed_payment_basepoint),
revocation_key=OnlyPubkeyKeypair(remote_revocation_basepoint),
to_self_delay=remote_delay,
dust_limit_sat=remote_dust_limit_sat,
max_htlc_value_in_flight_msat=remote_max_htlc_value_in_flight_msat,
max_accepted_htlcs=remote_max_accepted_htlcs
),
remote_state=RemoteState(
ctn = 0,
next_per_commitment_point=remote_funding_locked_msg["next_per_commitment_point"],
amount_sat=remote_amount
),
local_state=LocalState(
ctn = 0,
per_commitment_secret_seed=per_commitment_secret_seed,
amount_sat=local_amount
),
constraints=ChannelConstraints(capacity=funding_sat, feerate=local_feerate, is_initiator=True)
)
async def receive_commitment_revoke_ack(self, openchannel, expected_received_sat, payment_preimage):
channel_id = openchannel.channel_id
local_per_commitment_secret_seed = openchannel.local_state.per_commitment_secret_seed
assert openchannel.local_state.ctn == 0
local_next_pcs_index = 2**48 - 2
remote_funding_pubkey = openchannel.remote_config.multisig_key.pubkey
remote_next_commitment_point = openchannel.remote_state.next_per_commitment_point
remote_revocation_basepoint = openchannel.remote_config.revocation_key.pubkey
remote_htlc_basepoint = openchannel.remote_config.htlc_key.pubkey
local_htlc_basepoint = openchannel.local_config.htlc_key.pubkey
delayed_payment_basepoint = openchannel.local_config.delayed_key.pubkey
revocation_basepoint = openchannel.local_config.revocation_key.pubkey
remote_delayed_payment_basepoint = openchannel.remote_config.delayed_key.pubkey
remote_delay = openchannel.remote_config.to_self_delay
remote_dust_limit_sat = openchannel.remote_config.dust_limit_sat
funding_privkey = openchannel.local_config.multisig_key.privkey
htlc_privkey = openchannel.local_config.htlc_key.privkey
try:
commitment_signed_msg = await self.commitment_signed[channel_id]
finally:
del self.commitment_signed[channel_id]
# TODO make new future? (there could be more updates)
local_last_per_commitment_secret = get_per_commitment_secret_from_seed(local_per_commitment_secret_seed, local_last_pcs_index)
local_next_per_commitment_secret = get_per_commitment_secret_from_seed(local_per_commitment_secret_seed, local_last_pcs_index - 1)
local_next_per_commitment_secret = get_per_commitment_secret_from_seed(local_per_commitment_secret_seed, local_next_pcs_index)
local_next_per_commitment_point = secret_to_pubkey(int.from_bytes(
local_next_per_commitment_secret,
byteorder="big"))
@ -902,11 +957,6 @@ class Peer(PrintError):
amount_msat = int.from_bytes(self.unfulfilled_htlcs[0]["amount_msat"], "big")
remote_revocation_pubkey = derive_blinded_pubkey(remote_revocation_basepoint, local_next_per_commitment_point)
local_ctx_args = local_ctx_args._replace(remote_amount = local_ctx_args.remote_amount - expected_received_sat)
local_ctx_args = local_ctx_args._replace(ctn = local_next_commitment_number)
local_ctx_args = local_ctx_args._replace(remote_revocation_pubkey = remote_revocation_pubkey)
local_ctx_args = local_ctx_args._replace(remotepubkey = derive_pubkey(local_ctx_args.remote_payment_basepoint, local_next_per_commitment_point))
local_ctx_args = local_ctx_args._replace(local_delayedpubkey = derive_pubkey(delayed_payment_basepoint, local_next_per_commitment_point))
htlcs_in_local = [
(
@ -915,7 +965,23 @@ class Peer(PrintError):
)
]
new_commitment = make_commitment(*local_ctx_args, htlcs=htlcs_in_local)
new_commitment = make_commitment(
1,
openchannel.local_config.multisig_key.pubkey,
openchannel.remote_config.multisig_key.pubkey,
derive_pubkey(openchannel.remote_config.payment_key.pubkey, local_next_per_commitment_point),
openchannel.local_config.payment_key.pubkey,
openchannel.remote_config.payment_key.pubkey,
remote_revocation_pubkey,
derive_pubkey(delayed_payment_basepoint, local_next_per_commitment_point),
openchannel.local_config.to_self_delay,
*openchannel.funding_outpoint,
openchannel.constraints.capacity,
openchannel.local_state.amount_sat,
openchannel.remote_state.amount_sat - expected_received_sat,
openchannel.local_config.dust_limit_sat,
openchannel.constraints.feerate,
True, htlcs=htlcs_in_local)
preimage_hex = new_commitment.serialize_preimage(0)
pre_hash = bitcoin.Hash(bfh(preimage_hex))
if not bitcoin.verify_signature(remote_funding_pubkey, commitment_signed_msg["signature"], pre_hash):
@ -927,7 +993,13 @@ class Peer(PrintError):
# TODO verify htlc_signature
pubkeys = sorted([bh2u(local_ctx_args.funding_pubkey), bh2u(remote_funding_pubkey)])
local_last_pcs_index = 2**48 - openchannel.local_state.ctn - 1
local_last_per_commitment_secret = get_per_commitment_secret_from_seed(local_per_commitment_secret_seed, local_last_pcs_index)
self.send_message(gen_msg("revoke_and_ack", channel_id=channel_id, per_commitment_secret=local_last_per_commitment_secret, next_per_commitment_point=local_next_per_commitment_point))
funding_pubkey = openchannel.local_config.multisig_key.pubkey
pubkeys = sorted([bh2u(funding_pubkey), bh2u(remote_funding_pubkey)])
revocation_pubkey = derive_blinded_pubkey(revocation_basepoint, remote_next_commitment_point)
remote_delayedpubkey = derive_pubkey(remote_delayed_payment_basepoint, remote_next_commitment_point)
their_local_htlc_pubkey = derive_pubkey(remote_htlc_basepoint, remote_next_commitment_point)
@ -936,25 +1008,24 @@ class Peer(PrintError):
their_remote_htlc_privkey = their_remote_htlc_privkey_number.to_bytes(32, "big")
# TODO check payment_hash
htlcs_in_remote = [(make_offered_htlc(revocation_pubkey, their_remote_htlc_pubkey, their_local_htlc_pubkey, payment_hash), amount_msat)]
local_payment_pubkey = derive_pubkey(local_ctx_args.base_point, remote_next_commitment_point)
local_payment_pubkey = derive_pubkey(openchannel.local_config.payment_key.pubkey, remote_next_commitment_point)
remote_ctx = make_commitment(
1,
remote_funding_pubkey, local_ctx_args.funding_pubkey, local_payment_pubkey,
local_ctx_args.base_point, local_ctx_args.remote_payment_basepoint,
remote_funding_pubkey, funding_pubkey, local_payment_pubkey,
openchannel.local_config.payment_key.pubkey, openchannel.remote_config.payment_key.pubkey,
revocation_pubkey, remote_delayedpubkey, remote_delay,
local_ctx_args.funding_txid, local_ctx_args.funding_index, local_ctx_args.funding_satoshis,
local_ctx_args.remote_amount, local_ctx_args.local_amount, remote_dust_limit_satoshis, local_ctx_args.local_feerate, False, htlcs=htlcs_in_remote)
remote_ctx.sign({bh2u(local_ctx_args.funding_pubkey): (funding_privkey, True)})
sig_index = pubkeys.index(bh2u(local_ctx_args.funding_pubkey))
*openchannel.funding_outpoint, openchannel.constraints.capacity,
openchannel.remote_state.amount_sat - expected_received_sat, openchannel.local_state.amount_sat, remote_dust_limit_sat,
openchannel.constraints.feerate, False, htlcs=htlcs_in_remote)
remote_ctx.sign({bh2u(funding_pubkey): (funding_privkey, True)})
sig_index = pubkeys.index(bh2u(funding_pubkey))
sig = bytes.fromhex(remote_ctx.inputs()[0]["signatures"][sig_index])
r, s = sigdecode_der(sig[:-1], SECP256k1.generator.order())
sig_64 = sigencode_string_canonize(r, s, SECP256k1.generator.order())
self.send_message(gen_msg("revoke_and_ack", channel_id=channel_id, per_commitment_secret=local_last_per_commitment_secret, next_per_commitment_point=local_next_per_commitment_point))
htlc_tx_output = make_htlc_tx_output(
amount_msat = amount_msat,
local_feerate = local_ctx_args.local_feerate,
local_feerate = openchannel.constraints.feerate,
revocationpubkey=revocation_pubkey,
local_delayedpubkey=remote_delayedpubkey,
success = False) # timeout for the one offering an HTLC
@ -990,18 +1061,19 @@ class Peer(PrintError):
revocation_pubkey = derive_blinded_pubkey(revocation_basepoint, remote_next_commitment_point)
remote_delayedpubkey = derive_pubkey(remote_delayed_payment_basepoint, remote_next_commitment_point)
local_payment_pubkey = derive_pubkey(local_ctx_args.base_point, remote_next_commitment_point)
# local commitment transaction without htlcs
local_payment_pubkey = derive_pubkey(openchannel.local_config.payment_key.pubkey, remote_next_commitment_point)
# remote commitment transaction without htlcs
bare_ctx = make_commitment(
2,
remote_funding_pubkey, local_ctx_args.funding_pubkey, local_payment_pubkey,
local_ctx_args.base_point, local_ctx_args.remote_payment_basepoint,
remote_funding_pubkey, funding_pubkey, local_payment_pubkey,
openchannel.local_config.payment_key.pubkey, openchannel.remote_config.payment_key.pubkey,
revocation_pubkey, remote_delayedpubkey, remote_delay,
local_ctx_args.funding_txid, local_ctx_args.funding_index, local_ctx_args.funding_satoshis,
local_ctx_args.remote_amount, local_ctx_args.local_amount + expected_received_sat, remote_dust_limit_satoshis, local_ctx_args.local_feerate, False, htlcs=[])
*openchannel.funding_outpoint, openchannel.constraints.capacity,
openchannel.remote_state.amount_sat - expected_received_sat, openchannel.local_state.amount_sat + expected_received_sat,
remote_dust_limit_sat, openchannel.constraints.feerate, False, htlcs=[])
bare_ctx.sign({bh2u(local_ctx_args.funding_pubkey): (funding_privkey, True)})
sig_index = pubkeys.index(bh2u(local_ctx_args.funding_pubkey))
bare_ctx.sign({bh2u(funding_pubkey): (funding_privkey, True)})
sig_index = pubkeys.index(bh2u(funding_pubkey))
sig = bytes.fromhex(bare_ctx.inputs()[0]["signatures"][sig_index])
r, s = sigdecode_der(sig[:-1], SECP256k1.generator.order())
sig_64 = sigencode_string_canonize(r, s, SECP256k1.generator.order())

5
lib/tests/test_lnbase_online.py

@ -4,6 +4,7 @@ import json
import binascii
import asyncio
import time
import os
from lib.bitcoin import sha256
from decimal import Decimal
@ -50,12 +51,12 @@ if __name__ == "__main__":
async def async_test():
payment_preimage = bytes.fromhex("01"*32)
RHASH = sha256(payment_preimage)
channel_id, per_commitment_secret_seed, local_ctx_args, remote_funding_pubkey, remote_funding_locked_msg, remote_revocation_basepoint, remote_htlc_basepoint, local_htlc_basepoint, delayed_payment_basepoint, revocation_basepoint, remote_delayed_payment_basepoint, remote_delay, remote_dust_limit_satoshis, funding_privkey, htlc_privkey = await peer.channel_establishment_flow(wallet, config, funding_satoshis, push_msat)
openchannel = await peer.channel_establishment_flow(wallet, config, funding_satoshis, push_msat, temp_channel_id=os.urandom(32))
expected_received_sat = 400000
pay_req = lnencode(LnAddr(RHASH, amount=Decimal("0.00000001")*expected_received_sat, tags=[('d', 'one cup of coffee')]), peer.privkey[:32])
print("payment request", pay_req)
last_pcs_index = 2**48 - 1
await peer.receive_commitment_revoke_ack(channel_id, per_commitment_secret_seed, last_pcs_index, local_ctx_args, expected_received_sat, remote_funding_pubkey, local_next_commitment_number=1, remote_next_commitment_point=remote_funding_locked_msg["next_per_commitment_point"], remote_revocation_basepoint=remote_revocation_basepoint, remote_htlc_basepoint=remote_htlc_basepoint, local_htlc_basepoint=local_htlc_basepoint, delayed_payment_basepoint=delayed_payment_basepoint, revocation_basepoint=revocation_basepoint, remote_delayed_payment_basepoint=remote_delayed_payment_basepoint, remote_delay=remote_delay, remote_dust_limit_satoshis=remote_dust_limit_satoshis, funding_privkey=funding_privkey, htlc_privkey=htlc_privkey, payment_preimage=payment_preimage)
await peer.receive_commitment_revoke_ack(openchannel, expected_received_sat, payment_preimage)
fut = asyncio.run_coroutine_threadsafe(async_test(), network.asyncio_loop)
while not fut.done():
time.sleep(1)

Loading…
Cancel
Save