URI: 
       tlnbase: offered htlc script construction - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit a23aac76d3f5bdabae5e7379a7e1aba6f172670f
   DIR parent 1bc6958c831900b62746445a885a701f6e1d716e
  HTML Author: Janus <ysangkok@gmail.com>
       Date:   Mon, 16 Apr 2018 17:29:03 +0200
       
       lnbase: offered htlc script construction
       
       Diffstat:
         M lib/lnbase.py                       |      29 +++++++++++++++++++++++++++--
         M lib/tests/test_lnbase.py            |      40 +++++++++++++++++++++++++------
       
       2 files changed, 60 insertions(+), 9 deletions(-)
       ---
   DIR diff --git a/lib/lnbase.py b/lib/lnbase.py
       t@@ -21,6 +21,7 @@ import binascii
        import hashlib
        import hmac
        import cryptography.hazmat.primitives.ciphers.aead as AEAD
       +from . import ripemd
        
        from .bitcoin import (public_key_from_private_key, ser_to_point, point_to_ser,
                              string_to_number, deserialize_privkey, EC_KEY, rev_hex, int_to_hex,
       t@@ -260,10 +261,34 @@ def get_obscured_ctn(ctn, local, remote):
        def overall_weight(num_htlc):
            return 500 + 172 * num_htlc + 224
        
       +def make_offered_htlc(revocation_pubkey, remote_htlcpubkey, local_htlcpubkey, payment_preimage):
       +    assert type(revocation_pubkey) is bytes
       +    assert type(remote_htlcpubkey) is bytes
       +    assert type(local_htlcpubkey) is bytes
       +    assert type(payment_preimage) is bytes
       +    h = hashlib.new("ripemd160")
       +    h.update(payment_preimage)
       +    payment_hash = h.digest()#ripemd.new(payment_preimage).digest()
       +    assert type(payment_hash) is bytes
       +    return bytes([opcodes.OP_DUP, opcodes.OP_HASH160]) + bfh(push_script(bh2u(bitcoin.hash_160(revocation_pubkey)))) + bytes([opcodes.OP_EQUAL
       +     , opcodes.OP_IF
       +       , opcodes.OP_CHECKSIG
       +     , opcodes.OP_ELSE]) +\
       +       bfh(push_script(bh2u(remote_htlcpubkey))) + bytes([opcodes.OP_SWAP, opcodes.OP_SIZE]) + bitcoin.add_number_to_script(32) + bytes([opcodes.OP_EQUAL,
       +       opcodes.OP_NOTIF,
       +         # to local node via htlc-timeout transaction (timelocked)
       +         opcodes.OP_DROP]) + bitcoin.add_number_to_script(2) + bytes([opcodes.OP_SWAP]) + bfh(push_script(bh2u(local_htlcpubkey))) + bitcoin.add_number_to_script(2) + bytes([opcodes.OP_CHECKMULTISIG,
       +       opcodes.OP_ELSE,
       +         # to remote node with preimage
       +         opcodes.OP_HASH160]) + bfh(push_script(bh2u(payment_hash))) + bytes([opcodes.OP_EQUALVERIFY,
       +         opcodes.OP_CHECKSIG,
       +       opcodes.OP_ENDIF,
       +     opcodes.OP_ENDIF])
       +
        def make_commitment(ctn, local_funding_pubkey, remote_funding_pubkey, remotepubkey,
                            payment_pubkey, remote_payment_pubkey, revocation_pubkey, delayed_pubkey,
                            funding_txid, funding_pos, funding_satoshis,
       -                    to_local_msat, to_remote_msat, local_feerate, local_delay):
       +                    to_local_msat, to_remote_msat, local_feerate, local_delay, htlcs=[]):
            pubkeys = sorted([bh2u(local_funding_pubkey), bh2u(remote_funding_pubkey)])
            obs = get_obscured_ctn(ctn, payment_pubkey, remote_payment_pubkey)
            locktime = (0x20 << 24) + (obs & 0xffffff)
       t@@ -292,7 +317,7 @@ def make_commitment(ctn, local_funding_pubkey, remote_funding_pubkey, remotepubk
            to_local = (bitcoin.TYPE_ADDRESS, local_address, local_amount)
            to_remote = (bitcoin.TYPE_ADDRESS, remote_address, remote_amount)
            # no htlc for the moment
       -    c_outputs = [to_local, to_remote]
       +    c_outputs = [to_local, to_remote] + htlcs
            # create commitment tx
            tx = Transaction.from_io(c_inputs, c_outputs, locktime=locktime, version=2)
            tx.BIP_LI01_sort()
   DIR diff --git a/lib/tests/test_lnbase.py b/lib/tests/test_lnbase.py
       t@@ -1,9 +1,13 @@
        import json
        import unittest
        from lib.util import bh2u
       -from lib.lnbase import make_commitment, get_obscured_ctn, Peer
       +from lib.lnbase import make_commitment, get_obscured_ctn, Peer, make_offered_htlc
        from lib.transaction import Transaction
        from lib import bitcoin
       +import ecdsa.ellipticcurve
       +from ecdsa.curves import SECP256k1
       +from lib.util import bfh
       +from lib import bitcoin
        
        funding_tx_id = '8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be'
        funding_output_index = 0
       t@@ -60,17 +64,39 @@ class Test_LNBase(unittest.TestCase):
                # todo check order and other output
                self.assertEqual(str(our_commit_tx), ref_commit_tx_str)
        
       -    def commitment_tx_with_all_five_HTLCs_untrimmed_minimum_feerate(self):
       +    def test_commitment_tx_with_all_five_HTLCs_untrimmed_minimum_feerate(self):
                to_local_msat = 6988000000
                to_remote_msat = 3000000000
                local_feerate_per_kw = 0
                # base commitment transaction fee = 0
                # actual commitment transaction fee = 0
       -        # HTLC 2 offered amount 2000 wscript 76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868
       -        # HTLC 3 offered amount 3000 wscript 76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868
       -        # HTLC 0 received amount 1000 wscript 76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac6868
       -        # HTLC 1 received amount 2000 wscript 76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6868
       -        # HTLC 4 received amount 4000 wscript 76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6868
       +
       +        per_commitment_secret = 0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100
       +        per_commitment_point = SECP256k1.generator * per_commitment_secret 
       +
       +        remote_htlcpubkey = remotepubkey
       +        local_htlcpubkey = localpubkey
       +        htlc2_payment_preimage = b"\x02" * 32
       +        htlc2 = make_offered_htlc(local_revocation_pubkey, remote_htlcpubkey, local_htlcpubkey, htlc2_payment_preimage)
       +
       +        # HTLC 2 offered amount 2000
       +        # wscript 
       +        ref_htlc2_wscript = "76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868"
       +
       +        self.assertEqual(htlc2, bfh(ref_htlc2_wscript)) # TODO comparison fails on payment_hash
       +
       +        # HTLC 3 offered amount 3000 
       +        # wscript 
       +        ref_htlc3_wscript = "76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868"
       +        # HTLC 0 received amount 1000
       +        # wscript
       +        ref_htlc0_wscript = "76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac6868"
       +        # HTLC 1 received amount 2000 
       +        # wscript 
       +        ref_htlc1_wscript = "76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac6868"
       +        # HTLC 4 received amount 4000 
       +        # wscript 
       +        ref_htlc4_wscript = "76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac6868"
                # to_local amount 6988000 wscript 63210212a140cd0c6539d07cd08dfe09984dec3251ea808b892efeac3ede9402bf2b1967029000b2752103fd5960528dc152014952efdb702a88f71e3c1653b2314431701ec77e57fde83c68ac
                # to_remote amount 3000000 P2WPKH(0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b)
                remote_signature = "304402204fd4928835db1ccdfc40f5c78ce9bd65249b16348df81f0c44328dcdefc97d630220194d3869c38bc732dd87d13d2958015e2fc16829e74cd4377f84d215c0b70606"