URI: 
       tln: do not use mSAT accuracy for commitment fees - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 9853cc6f3139d8f4734d366c0536989aee71009c
   DIR parent 66e7b4d25020ce1a01903116f63fd7f79b2a6d48
  HTML Author: Janus <ysangkok@gmail.com>
       Date:   Fri, 20 Jul 2018 16:17:18 +0200
       
       ln: do not use mSAT accuracy for commitment fees
       
       Diffstat:
         M electrum/lnhtlc.py                  |      10 ++++++----
         M electrum/lnutil.py                  |       7 +++----
         M electrum/tests/test_lnhtlc.py       |      21 +++++++++++++++------
       
       3 files changed, 24 insertions(+), 14 deletions(-)
       ---
   DIR diff --git a/electrum/lnhtlc.py b/electrum/lnhtlc.py
       t@@ -2,7 +2,7 @@
        from collections import namedtuple
        import binascii
        import json
       -from .util import bfh, PrintError
       +from .util import bfh, PrintError, bh2u
        from .bitcoin import Hash
        from .bitcoin import redeem_script_to_address
        from .crypto import sha256
       t@@ -199,14 +199,16 @@ class HTLCStateMachine(PrintError):
        
                for_us = False
        
       +        feerate = self.pending_remote_feerate
       +
                htlcsigs = []
                for we_receive, htlcs in zip([True, False], [self.htlcs_in_remote, self.htlcs_in_local]):
                    assert len(htlcs) <= 1
                    for htlc in htlcs:
                        weight = HTLC_SUCCESS_WEIGHT if we_receive else HTLC_TIMEOUT_WEIGHT
       -                fee = self.remote_state.feerate // 1000 * weight
       +                fee = feerate // 1000 * weight
                        if htlc.amount_msat // 1000 < self.remote_config.dust_limit_sat + fee:
       -                    print("value too small, skipping. htlc amt: {}, weight: {}, remote feerate {}, remote dust limit {}".format( htlc.amount_msat, weight, self.remote_state.feerate, self.remote_config.dust_limit_sat))
       +                    print("value too small, skipping. htlc amt: {}, weight: {}, remote feerate {}, remote dust limit {}".format( htlc.amount_msat, weight, feerate, self.remote_config.dust_limit_sat))
                            continue
                        original_htlc_output_index = 0
                        args = [self.remote_state.next_per_commitment_point, for_us, we_receive, htlc.amount_msat + htlc.total_fee, htlc.cltv_expiry, htlc.payment_hash, self.pending_remote_commitment, original_htlc_output_index]
       t@@ -244,7 +246,7 @@ class HTLCStateMachine(PrintError):
                preimage_hex = self.pending_local_commitment.serialize_preimage(0)
                pre_hash = Hash(bfh(preimage_hex))
                if not ecc.verify_signature(self.remote_config.multisig_key.pubkey, sig, pre_hash):
       -            raise Exception('failed verifying signature of our updated commitment transaction: ' + str(sig))
       +            raise Exception('failed verifying signature of our updated commitment transaction: ' + bh2u(sig) + ' preimage is ' + preimage_hex)
        
                _, this_point, _ = self.points
        
   DIR diff --git a/electrum/lnutil.py b/electrum/lnutil.py
       t@@ -153,6 +153,7 @@ def make_htlc_tx_output(amount_msat, local_feerate, revocationpubkey, local_dela
            p2wsh = bitcoin.redeem_script_to_address('p2wsh', bh2u(script))
            weight = HTLC_SUCCESS_WEIGHT if success else HTLC_TIMEOUT_WEIGHT
            fee = local_feerate * weight
       +    fee = fee // 1000 * 1000
            final_amount_sat = (amount_msat - fee) // 1000
            assert final_amount_sat > 0, final_amount_sat
            output = (bitcoin.TYPE_ADDRESS, p2wsh, final_amount_sat)
       t@@ -242,7 +243,7 @@ def make_htlc_tx_with_open_channel(chan, pcp, for_us, we_receive, amount_msat, c
            is_htlc_success = for_us == we_receive
            htlc_tx_output = make_htlc_tx_output(
                amount_msat = amount_msat,
       -        local_feerate = chan.local_state.feerate if for_us else chan.remote_state.feerate,
       +        local_feerate = chan.pending_local_feerate if for_us else chan.pending_remote_feerate,
                revocationpubkey=revocation_pubkey,
                local_delayedpubkey=delayedpubkey,
                success = is_htlc_success,
       t@@ -295,13 +296,11 @@ def make_commitment(ctn, local_funding_pubkey, remote_funding_pubkey,
            remote_address = make_commitment_output_to_remote_address(remote_payment_pubkey)
            # TODO trim htlc outputs here while also considering 2nd stage htlc transactions
            fee = local_feerate * overall_weight(len(htlcs))
       -    assert type(fee) is int
       +    fee = fee // 1000 * 1000
            we_pay_fee = for_us == we_are_initiator
            to_local_amt = local_amount - (fee if we_pay_fee else 0)
       -    assert type(to_local_amt) is int
            to_local = (bitcoin.TYPE_ADDRESS, local_address, to_local_amt // 1000)
            to_remote_amt = remote_amount - (fee if not we_pay_fee else 0)
       -    assert type(to_remote_amt) is int
            to_remote = (bitcoin.TYPE_ADDRESS, remote_address, to_remote_amt // 1000)
            c_outputs = [to_local, to_remote]
            for script, msat_amount in htlcs:
   DIR diff --git a/electrum/tests/test_lnhtlc.py b/electrum/tests/test_lnhtlc.py
       t@@ -74,12 +74,12 @@ def bip32(sequence):
            assert type(k) is bytes
            return k
        
       -def create_test_channels():
       +def create_test_channels(feerate=6000, local=None, remote=None):
            funding_txid = binascii.hexlify(os.urandom(32)).decode("ascii")
            funding_index = 0
       -    funding_sat = bitcoin.COIN * 10
       -    local_amount = (funding_sat * 1000) // 2
       -    remote_amount = (funding_sat * 1000) // 2
       +    funding_sat = ((local + remote) // 1000) if local is not None and remote is not None else (bitcoin.COIN * 10)
       +    local_amount = local if local is not None else (funding_sat * 1000 // 2)
       +    remote_amount = remote if remote is not None else (funding_sat * 1000 // 2)
            alice_raw = [ bip32("m/" + str(i)) for i in range(5) ]
            bob_raw = [ bip32("m/" + str(i)) for i in range(5,11) ]
            alice_privkeys = [lnbase.Keypair(lnbase.privkey_to_pubkey(x), x) for x in alice_raw]
       t@@ -97,12 +97,21 @@ def create_test_channels():
        
            return \
                lnhtlc.HTLCStateMachine(
       -            create_channel_state(funding_txid, funding_index, funding_sat, 6000, True, local_amount, remote_amount, alice_privkeys, bob_pubkeys, alice_seed, bob_cur, bob_next, b"\x02"*33, l_dust=200, r_dust=1300, l_csv=5, r_csv=4), "alice"), \
       +            create_channel_state(funding_txid, funding_index, funding_sat, feerate, True, local_amount, remote_amount, alice_privkeys, bob_pubkeys, alice_seed, bob_cur, bob_next, b"\x02"*33, l_dust=200, r_dust=1300, l_csv=5, r_csv=4), "alice"), \
                lnhtlc.HTLCStateMachine(
       -            create_channel_state(funding_txid, funding_index, funding_sat, 6000, False, remote_amount, local_amount, bob_privkeys, alice_pubkeys, bob_seed, alice_cur, alice_next, b"\x01"*33, l_dust=1300, r_dust=200, l_csv=4, r_csv=5), "bob")
       +            create_channel_state(funding_txid, funding_index, funding_sat, feerate, False, remote_amount, local_amount, bob_privkeys, alice_pubkeys, bob_seed, alice_cur, alice_next, b"\x01"*33, l_dust=1300, r_dust=200, l_csv=4, r_csv=5), "bob")
        
        one_bitcoin_in_msat = bitcoin.COIN * 1000
        
       +class TestFee(unittest.TestCase):
       +    """
       +    test
       +    https://github.com/lightningnetwork/lightning-rfc/blob/e0c436bd7a3ed6a028e1cb472908224658a14eca/03-transactions.md#requirements-2
       +    """
       +    def test_SimpleAddSettleWorkflow(self):
       +        alice_channel, bob_channel = create_test_channels(253, 10000000000, 5000000000)
       +        self.assertIn(9999817, [x[2] for x in alice_channel.local_commitment.outputs()])
       +
        class TestLNBaseHTLCStateMachine(unittest.TestCase):
            def assertOutputExistsByValue(self, tx, amt_sat):
                for typ, scr, val in tx.outputs():