electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 7b6f64a402bf4836cae4ab825988ed07cdeaf75e
parent 52ae63990ff9c3af19c10256cbfdebb9de776937
Author: ThomasV <thomasv@electrum.org>
Date:   Fri, 13 Apr 2018 15:17:14 +0200

lnbase: create unit test for commitment tx

Diffstat:
Mlib/lnbase.py | 72++++++++++++++++++++++++++++++++++++++++++++----------------------------
Alib/tests/test_lnbase.py | 49+++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 93 insertions(+), 28 deletions(-)

diff --git a/lib/lnbase.py b/lib/lnbase.py @@ -21,12 +21,12 @@ import hashlib import hmac import cryptography.hazmat.primitives.ciphers.aead as AEAD -from .bitcoin import public_key_from_private_key, ser_to_point, point_to_ser, string_to_number, deserialize_privkey, EC_KEY, rev_hex +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 from . import bitcoin from .constants import set_testnet, set_simnet from . import constants from . import transaction -from .util import PrintError, bh2u +from .util import PrintError, bh2u, print_error from .wallet import Wallet from .storage import WalletStorage from .transaction import opcodes, Transaction @@ -248,6 +248,45 @@ def aiosafe(f): traceback.print_exc() return f2 +def get_locktime(cn, local, remote): + print_error(len(local), len(remote)) + q = local + remote + mask = int.from_bytes(H256(q)[-6:], byteorder="big") + print_error('mask', hex(mask)) + obs = cn ^ mask + print_error('obs ', hex(obs)) + locktime = (0x20 << 48) + obs + return locktime + +def make_commitment(local_pubkey, remote_pubkey, payment_pubkey, remote_payment_pubkey, revocation_pubkey, delayed_pubkey, funding_txid, funding_pos, funding_satoshis): + pubkeys = sorted([bh2u(local_pubkey), bh2u(remote_pubkey)]) + # commitment tx input + c_inputs = [{ + 'type': 'p2wsh', + 'x_pubkeys': pubkeys, + 'signatures':[None, None], + 'num_sig': 2, + 'prevout_n': funding_pos, + 'prevout_hash': funding_txid, + 'value': funding_satoshis, + 'coinbase': False + }] + # commitment tx outputs + local_script = bytes([opcodes.OP_IF]) + revocation_pubkey + bytes([opcodes.OP_ELSE, opcodes.OP_CSV, opcodes.OP_DROP]) + delayed_pubkey + bytes([opcodes.OP_ENDIF, opcodes.OP_CHECKSIG]) + local_address = bitcoin.redeem_script_to_address('p2wsh', bh2u(local_script)) + local_amount = funding_satoshis + remote_address = bitcoin.pubkey_to_address('p2wpkh', bh2u(remote_pubkey)) + remote_amount = 0 + 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] + # create commitment tx + locktime = get_locktime(0, payment_pubkey, remote_payment_pubkey) + print_error('locktime', locktime, hex(locktime)) + tx = Transaction.from_io(c_inputs, c_outputs, locktime=locktime, version=2) + return tx + class Peer(PrintError): def __init__(self, host, port, pubkey): @@ -418,36 +457,13 @@ class Peer(PrintError): pubkeys = sorted([bh2u(funding_pubkey), bh2u(remote_pubkey)]) redeem_script = transaction.multisig_script(pubkeys, 2) funding_address = bitcoin.redeem_script_to_address('p2wsh', redeem_script) - #TODO support passwd, fix fee funding_output = (bitcoin.TYPE_ADDRESS, funding_address, funding_satoshis) funding_tx = wallet.mktx([funding_output], None, config, 1000) funding_index = funding_tx.outputs().index(funding_output) - # commitment tx input - c_inputs = [{ - 'type': 'p2wsh', - 'x_pubkeys': pubkeys, - 'signatures':[None, None], - 'num_sig': 2, - 'prevout_n': funding_index, - 'prevout_hash': funding_tx.txid(), - 'value': funding_satoshis, - 'coinbase': False - }] - # commitment tx outputs - local_script = bytes([opcodes.OP_IF]) + revocation_pubkey + bytes([opcodes.OP_ELSE, opcodes.OP_CSV, opcodes.OP_DROP]) + delayed_pubkey + bytes([opcodes.OP_ENDIF, opcodes.OP_CHECKSIG]) - local_address = bitcoin.redeem_script_to_address('p2wsh', bh2u(local_script)) - local_amount = funding_satoshis - remote_address = bitcoin.pubkey_to_address('p2wpkh', bh2u(remote_pubkey)) - remote_amount = 0 - 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] - # create commitment tx - c_tx = Transaction.from_io(c_inputs, c_outputs) + remote_payment_pubkey = accept_channel['payment_basepoint'] + c_tx = make_commitment(funding_pubkey, remote_pubkey, payment_pubkey, remote_payment_pubkey, revocation_pubkey, delayed_pubkey, funding_tx.txid(), funding_index, funding_satoshis) c_tx.sign({bh2u(funding_pubkey): (funding_privkey, True)}) - # - self.print_error('ctx inputs', c_tx.inputs()) + sig_index = pubkeys.index(bh2u(funding_pubkey)) sig = bytes.fromhex(c_tx.inputs()[0]["signatures"][sig_index]) self.print_error('sig', len(sig)) diff --git a/lib/tests/test_lnbase.py b/lib/tests/test_lnbase.py @@ -0,0 +1,49 @@ +import unittest +from lib.util import bh2u +from lib.lnbase import make_commitment, get_locktime + +class Test_LNBase(unittest.TestCase): + + def test_commitment_tx(self): + + funding_tx_id = '8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be' + funding_output_index = 0 + funding_amount_satoshi = 10000000 + commitment_number = 42 + local_delay = 144 + local_dust_limit_satoshi = 546 + + local_payment_basepoint = bytes.fromhex('034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa') + remote_payment_basepoint = bytes.fromhex('032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991') + locktime = get_locktime(42, local_payment_basepoint, remote_payment_basepoint) + + local_funding_privkey = bytes.fromhex('30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f374901') + local_funding_pubkey = bytes.fromhex('023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb') + remote_funding_pubkey = bytes.fromhex('030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1') + local_privkey = bytes.fromhex('bb13b121cdc357cd2e608b0aea294afca36e2b34cf958e2e6451a2f27469449101') + localpubkey = bytes.fromhex('030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e7') + remotepubkey = bytes.fromhex('0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b') + local_delayedpubkey = bytes.fromhex('03fd5960528dc152014952efdb702a88f71e3c1653b2314431701ec77e57fde83c') + local_revocation_pubkey = bytes.fromhex('0212a140cd0c6539d07cd08dfe09984dec3251ea808b892efeac3ede9402bf2b19') + # funding wscript = 5221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae + + #name: simple commitment tx with no HTLCs + to_local_msat = 7000000000 + to_remote_msat = 3000000000 + local_feerate_per_kw = 15000 + # base commitment transaction fee = 10860 + # actual commitment transaction fee = 10860 + # to_local amount 6989140 wscript 63210212a140cd0c6539d07cd08dfe09984dec3251ea808b892efeac3ede9402bf2b1967029000b2752103fd5960528dc152014952efdb702a88f71e3c1653b2314431701ec77e57fde83c68ac + # to_remote amount 3000000 P2WPKH(0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b) + #remote_signature = 3045022100f51d2e566a70ba740fc5d8c0f07b9b93d2ed741c3c0860c613173de7d39e7968022041376d520e9c0e1ad52248ddf4b22e12be8763007df977253ef45a4ca3bdb7c0 + # local_signature = 3044022051b75c73198c6deee1a875871c3961832909acd297c6b908d59e3319e5185a46022055c419379c5051a78d00dbbce11b5b664a0c22815fbcc6fcef6b1937c3836939 + #num_htlcs: 0 + c_tx = make_commitment( + local_funding_pubkey, remote_funding_pubkey, + local_payment_basepoint, remote_payment_basepoint, + local_revocation_pubkey, local_delayedpubkey, + funding_tx_id, funding_output_index, funding_amount_satoshi) + + commit_tx = '02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8002c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de84311054a56a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400473044022051b75c73198c6deee1a875871c3961832909acd297c6b908d59e3319e5185a46022055c419379c5051a78d00dbbce11b5b664a0c22815fbcc6fcef6b1937c383693901483045022100f51d2e566a70ba740fc5d8c0f07b9b93d2ed741c3c0860c613173de7d39e7968022041376d520e9c0e1ad52248ddf4b22e12be8763007df977253ef45a4ca3bdb7c001475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220' + self.assertEqual(str(c_tx), commit_tx) +