Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lightning open channel: Duplicated output, funds lost #7298

Closed
ondra-novak opened this issue May 15, 2021 · 12 comments
Closed

Lightning open channel: Duplicated output, funds lost #7298

ondra-novak opened this issue May 15, 2021 · 12 comments
Labels
bug 🐞 lightning ⚡ topic-wallet 👛 related to wallet.py, or maybe address_synchronizer.py/coinchooser.py
Milestone

Comments

@ondra-novak
Copy link

4.1.2

I have very weird open-channel transaction (trampoline mode)

https://blockstream.info/tx/2aebbc581ae7d374006ae6abbb7f9a3d7953657661130249a3db780958238eff

Funds are probably lost

Reproduction steps

  1. using HW wallet Trezor
  2. open channel to Electrum trampoline
  3. fail to sign transaction (wrong pin)
  4. channel appears in list, not funded
  5. try to close channel (state shutdown) - cannot be deleted
  6. open another trampoline channel
  7. now transaction has two outputs.

Is there any way how to recover the funds from second output?

TY.

@SomberNight
Copy link
Member

SomberNight commented May 15, 2021

I can reproduce.
The user also needs to have Preferences>Transactions>Batch RBF transactions enabled to trigger it.

The high level flow is this:

  • try to open channel1
  • tx signing fails, but unsigned funding tx gets saved into History as "Local" tx1
  • at this point user could select tx1 in History, sign it and broadcast it, and the channel would open normally,
  • but here instead OP tried to open channel2, and had Batch RBF transactions enabled
  • the funding tx constructed for channel2 will be "tx1 plus funding output for channel2": tx2
  • and hence tx2 creates two funding outputs, one for channel1, one for channel2, but the outpoint for channel1 is not what was sent in "funding_created"

So the critical bug is that Batch RBF transactions should not merge txs that are channel opens...
Another smaller bug is that inputting the HWW PIN incorrectly continues the flow instead of re-prompting for correct PIN.

using HW wallet Trezor

Note that the hardware wallet prompts the user twice; one for each foreign output, and also shows the total value of coins leaving the wallet (which is double than expected).

@SomberNight SomberNight added bug 🐞 lightning ⚡ topic-wallet 👛 related to wallet.py, or maybe address_synchronizer.py/coinchooser.py labels May 15, 2021
@SomberNight SomberNight added this to the 4.1.3 milestone May 15, 2021
SomberNight added a commit that referenced this issue May 15, 2021
The "Batch RBF transactions" feature mutates existing "local" and "unconfirmed RBF"
transactions when creating new transactions: it simply adds the new outputs to the
existing txs (and updates the change).
The "RBF" flag is only enforced for unconfirmed txs, not for local txs.
The bug was that given a local LN funding tx, when creating a new channel
with "batch_rbf" enabled, we would modify the existing local tx, and
broadcast that.

related: #7298
@SomberNight
Copy link
Member

open channel to Electrum trampoline
Is there any way how to recover the funds from second output?

I don't know.

The "Electrum trampoline" node runs eclair.
I think it might remember the funding privkey for 2016 blocks, based on:
https://github.com/ACINQ/eclair/blob/898c17bc76c1af9077314958612ad96c019bd381/eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala#L95
So it might not be deleted yet.

https://blockstream.info/tx/2aebbc581ae7d374006ae6abbb7f9a3d7953657661130249a3db780958238eff

So the output in question is 2aebbc581ae7d374006ae6abbb7f9a3d7953657661130249a3db780958238eff:2
(scriptPubKey 0020ee2da857e8f69f974d6491e083ad8dbde60a7b77f840eab722e9507abdfc641c).

Could you also share the corresponding channel id? In Electrum, Channels tab, right-click on channel>Copy>Long Channel ID.

@ecdsa could you save a copy of the output of $ eclair-cli channels, on the "Electrum trampoline" node?
For a given channel, the value for jq .data.commitments.localParams.fundingKeyPath looks relevant.

@ondra-novak
Copy link
Author

ondra-novak commented May 15, 2021

Note that the hardware wallet prompts the user twice; one for each foreign output, and also shows the total value of coins leaving the wallet (which is double than expected).

I known, but i am new to the topic, so I fully trusted Electrum that everything was right. This is my fault.

would appreciate if it were possible to use advanced payment dialog (Transaction detail before you sign and broadcast the transction, where you can check outputs and choose minig fee - i am using it for every payment - aka Advanced preview)

the Output in question leads to this address https://blockstream.info/address/bc1qack6s4lg760ewntyj8sg8tvdhhnq57mhlpqw4deza9g8400uvswql6jw6y (you are right, it has index 2 of the transaction)

Details about the failed channel

NodeID: 03ecef675be448b615e6176424070673ef8284e0fd19d8be062a6cb5b130a0a0d1
ChannelID: 73081356764b4c4ea0d1e14947ebcb86613ba45a75625caac9b9fbeebf3fec28

The output: 2aebbc581ae7d374006ae6abbb7f9a3d7953657661130249a3db780958238eff:0 is change address which is also under my control (bc1qlrv0gx3ddh07ut5835fmkx098kwdqjnhemhkng)

image

(transaction ID actualy doesn't exists)

The user also needs to have Preferences>Transactions>Batch RBF transactions enabled to trigger it.

I have RBF turned off, however, the Batch RBF transactions is enabled (and grayed out). I learned that funding transactions are always RBF, so this option can be in effect.

@SomberNight
Copy link
Member

SomberNight commented May 15, 2021

You can find the two pubkeys that compose the 2of2 multisig funding output by running these in the Console tab in Electrum:

>>> wallet.lnworker.channels[bytes.fromhex("73081356764b4c4ea0d1e14947ebcb86613ba45a75625caac9b9fbeebf3fec28")].config[lnutil.LOCAL].multisig_key.pubkey.hex()
>>> wallet.lnworker.channels[bytes.fromhex("73081356764b4c4ea0d1e14947ebcb86613ba45a75625caac9b9fbeebf3fec28")].config[lnutil.REMOTE].multisig_key.pubkey.hex()

Could you please share what they output?


You can also get the private key for one of these pubkeys similarly, your own, the LOCAL one.
Do not share this private key with anyone though.

>>> wallet.lnworker.channels[bytes.fromhex("73081356764b4c4ea0d1e14947ebcb86613ba45a75625caac9b9fbeebf3fec28")].config[lnutil.LOCAL].multisig_key.privkey.hex()

@ondra-novak
Copy link
Author

>>> wallet.lnworker.channels[bytes.fromhex("73081356764b4c4ea0d1e14947ebcb86613ba45a75625caac9b9fbeebf3fec28")].config[lnutil.LOCAL].multisig_key.pubkey.hex()
'03d82db36b7b896077ab0d2b8165a3517a1ee363aa9e9f7bfa2fcfa14ccc81ef03'
>>> wallet.lnworker.channels[bytes.fromhex("73081356764b4c4ea0d1e14947ebcb86613ba45a75625caac9b9fbeebf3fec28")].config[lnutil.REMOTE].multisig_key.pubkey.hex()
'0308ecbd369c42f3cd8d06cbedd754dfa2c24c8a4bca78a0e824f9c385d9b8da52'

SomberNight added a commit that referenced this issue Jun 7, 2021
This is easier to understand; the special case is not worth it.

related #7298
@SomberNight
Copy link
Member

SomberNight commented Jun 8, 2021

@ondra-novak If you share a receive address for your coins, we will try to help recover them. Will probably create a PSBT and share that and some instructions.


I've spent some time looking at the eclair source code and figured out how we can extract the funding private key.

Example below (using regtest).

In Electrum Qt, "Console" tab:

>>> wallet.lnworker.channels[bytes.fromhex("1c8b738a201ae50f84d7b2ad8ea88d7edbb138ec52ba09a58efd5928aff646af")].config[lnutil.LOCAL].multisig_key.pubkey.hex()
'03afb4f17a33d8214b98e493d9ccbe39e9aba9aeb736ecbde0fc1376f06036f882'
>>> wallet.lnworker.channels[bytes.fromhex("1c8b738a201ae50f84d7b2ad8ea88d7edbb138ec52ba09a58efd5928aff646af")].config[lnutil.REMOTE].multisig_key.pubkey.hex()
'03b4e5523792aee1e85348c415468460243620994e87973b5020cd5bd8f9a8ae33'

On server running eclair:

$ ./eclair-node-0.6.0-f89b092/bin/eclair-cli -a 127.0.0.1:8081 -p password channel --channelId="1c8b738a201ae50f84d7b2ad8ea88d7edbb138ec52ba09a58efd5928aff646af" | jq .data.commitments.localParams.fundingKeyPath
{
  "path": [
    3755043923,
    531178060,
    812164327,
    175720210,
    1752802332,
    4211578977,
    2973568850,
    2128943046,
    2147483648
  ]
}

$ cat ~/.eclair/channel_seed.dat | xxd -p | tr -d \\n
a72ee9e6e9c8f44ffca252e5b6238484d2d17da7a984981dbdfabb9c62b68369

Python script to calc funding privkey using above data.

#!/usr/bin/env python
#
# refs:
# https://github.com/ACINQ/eclair/blob/76894bd2e1cba226d618ffd28aa38f5da4228f97/eclair-core/src/main/scala/fr/acinq/eclair/crypto/keymanager/LocalChannelKeyManager.scala#L75
# https://github.com/ACINQ/eclair/blob/af618bc44fe6054957f65d77000a460c14b41f30/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala#L704

from electrum.bip32 import BIP32_PRIME, BIP32Node

#with open("/home/user/.eclair/channel_seed.dat", "rb") as f:
#    channel_seed = f.read()
channel_seed = bytes.fromhex("a72ee9e6e9c8f44ffca252e5b6238484d2d17da7a984981dbdfabb9c62b68369")

# chainhash based der path prefix
# see https://github.com/ACINQ/eclair/blob/76894bd2e1cba226d618ffd28aa38f5da4228f97/eclair-core/src/main/scala/fr/acinq/eclair/crypto/keymanager/LocalChannelKeyManager.scala#L35
derpath = [46 | BIP32_PRIME, 1 | BIP32_PRIME,]
# if mainnet, use this instead:
# derpath = [47 | BIP32_PRIME, 1 | BIP32_PRIME,]

# from "channel" RPC, "fundingKeyPath"
# e.g.
# $ ./eclair-node-0.6.0-f89b092/bin/eclair-cli -a 127.0.0.1:8081 -p password channel --channelId="1c8b738a201ae50f84d7b2ad8ea88d7edbb138ec52ba09a58efd5928aff646af" | jq .data.commitments.localParams.fundingKeyPath
# see https://github.com/ACINQ/eclair/blob/76894bd2e1cba226d618ffd28aa38f5da4228f97/eclair-core/src/main/scala/fr/acinq/eclair/crypto/keymanager/LocalChannelKeyManager.scala#L61
derpath += [
	3755043923,
	531178060,
	812164327,
	175720210,
	1752802332,
	4211578977,
	2973568850,
	2128943046,
	2147483648,
]
# add 0' for "funding"
# see https://github.com/ACINQ/eclair/blob/76894bd2e1cba226d618ffd28aa38f5da4228f97/eclair-core/src/main/scala/fr/acinq/eclair/crypto/keymanager/LocalChannelKeyManager.scala#L83
derpath += [
	0 | BIP32_PRIME,
]


rootnode = BIP32Node.from_rootseed(channel_seed, xtype="standard")
node = rootnode.subkey_at_private_derivation(derpath)

pubkey = node.eckey.get_public_key_bytes()
privkey = node.eckey.get_secret_bytes()
print(f"{pubkey.hex()=}, {privkey.hex()=}")

prints: pubkey.hex()='03b4e5523792aee1e85348c415468460243620994e87973b5020cd5bd8f9a8ae33', privkey.hex()='334e8f11d5aa5ee5269b471d60824f8909583e407a5c14cbf6a4f83b71ce65fe'

@SomberNight
Copy link
Member

>>> wallet.lnworker.channels[bytes.fromhex("73081356764b4c4ea0d1e14947ebcb86613ba45a75625caac9b9fbeebf3fec28")].config[lnutil.LOCAL].multisig_key.pubkey.hex()
'03d82db36b7b896077ab0d2b8165a3517a1ee363aa9e9f7bfa2fcfa14ccc81ef03'
>>> wallet.lnworker.channels[bytes.fromhex("73081356764b4c4ea0d1e14947ebcb86613ba45a75625caac9b9fbeebf3fec28")].config[lnutil.REMOTE].multisig_key.pubkey.hex()
'0308ecbd369c42f3cd8d06cbedd754dfa2c24c8a4bca78a0e824f9c385d9b8da52'

@ondra-novak If you share a receive address for your coins, we will try to help recover them. Will probably create a PSBT and share that and some instructions.

I have the privkey corresponding to 0308ecbd369c42f3cd8d06cbedd754dfa2c24c8a4bca78a0e824f9c385d9b8da52.
If you share an address to send the coins to, I will create a PSBT signed with this key and walk you through signing with yours.

@SomberNight SomberNight modified the milestone: 4.1.3 Jun 16, 2021
@ondra-novak
Copy link
Author

Sorry, i did not receive a notification.

There si bc1qvd7a7eun3cfet92z65g2qvw009malwlvrljpq9

@SomberNight
Copy link
Member

Ok, so for my own future reference, here is a testnet example:

cosigner1 runs:

from electrum.bitcoin import script_to_p2wsh
from electrum.transaction import multisig_script, tx_from_any, TxOutpoint, PartialTxInput, PartialTxOutput, PartialTransaction
from electrum import constants, ecc

constants.set_testnet()

PUBKEYS = sorted(["0205e38ad66cb9e2df713c58d3e46d5f04a286c857ff2989fc53bd9fe0e7291eb5", "026fe5febc72cd073030563452a6473993da59b2d78fd932ef3097fa6e712fd90b"])
FUNDING_TX_HEX = "020000000001017739eb9015b0d83d24893703ae37ed2c9abf3be4bd66dcba01d1a207d2830bc40100000000fdffffff02f2e90300000000002200201800ad21c0af3c9cb1a66516b14e9bd0db42604d79d069d30d2081c40a1ac3bb95cf80000000000016001488e83a321119f5993989ff6289bf0a159cc3cb5702473044022033d8434f2ed87032311755cce3ab4e79e8da7eda7a3988f053adfaf8cb7287750220595ffe4cb5b8660c986902e5fdee8475ca443eeaefbd3179e63effa440e389ba0121021667f66862f988885e0f221830e8c342cdc1e57d26db4d401a61eb708e74658a22951e00"
FUNDING_OUTIDX = 0
MYPRIVKEY1 = bytes.fromhex("678b14d6e0ad468841d666e231e000dbe88daacc6f34de623e388588c610479f")
DEST_ADDRESS = "tb1q4ndwks7ykg737pteg9pnzxfckfkvueyspjxl9s"
FEERATE = 20

witness_script = multisig_script(PUBKEYS, 2)
funding_addr = script_to_p2wsh(witness_script)
funding_tx = tx_from_any(FUNDING_TX_HEX)
assert funding_tx.outputs()[FUNDING_OUTIDX].address == funding_addr

mypubkey1 = ecc.ECPrivkey(MYPRIVKEY1).get_public_key_bytes()
assert mypubkey1.hex() in PUBKEYS


invalue = funding_tx.outputs()[FUNDING_OUTIDX].value
prevout = TxOutpoint(txid=bytes.fromhex(funding_tx.txid()), out_idx=FUNDING_OUTIDX)
txin = PartialTxInput(prevout=prevout)
txin.utxo = funding_tx
txin.script_type = 'p2wsh'
txin.pubkeys = [bytes.fromhex(pk) for pk in PUBKEYS]
txin.num_sig = 2

fee = 138 * FEERATE
outvalue = invalue - fee
txouts = [PartialTxOutput.from_address_and_value(DEST_ADDRESS, outvalue)]
sweep_tx = PartialTransaction.from_io([txin], txouts)
sweep_tx.set_rbf(True)
sweep_tx.sign({mypubkey1.hex(): (MYPRIVKEY1, True)})
print(str(sweep_tx))

cosigner2 runs:

from electrum.bitcoin import script_to_p2wsh
from electrum.transaction import multisig_script, tx_from_any, TxOutpoint, PartialTxInput, PartialTxOutput, PartialTransaction
from electrum import constants, ecc

constants.set_testnet()

PUBKEYS = sorted(["0205e38ad66cb9e2df713c58d3e46d5f04a286c857ff2989fc53bd9fe0e7291eb5", "026fe5febc72cd073030563452a6473993da59b2d78fd932ef3097fa6e712fd90b"])
FUNDING_TX_HEX = "020000000001017739eb9015b0d83d24893703ae37ed2c9abf3be4bd66dcba01d1a207d2830bc40100000000fdffffff02f2e90300000000002200201800ad21c0af3c9cb1a66516b14e9bd0db42604d79d069d30d2081c40a1ac3bb95cf80000000000016001488e83a321119f5993989ff6289bf0a159cc3cb5702473044022033d8434f2ed87032311755cce3ab4e79e8da7eda7a3988f053adfaf8cb7287750220595ffe4cb5b8660c986902e5fdee8475ca443eeaefbd3179e63effa440e389ba0121021667f66862f988885e0f221830e8c342cdc1e57d26db4d401a61eb708e74658a22951e00"
FUNDING_OUTIDX = 0
MYPRIVKEY2 = bytes.fromhex("b326d9d8597a51357caa9f954e4eb3cab980835025344c0d0549482639bbb57d")
SWEEP_TX = tx_from_any("cHNidP8BAFICAAAAAfjJ0TgWhObT3OZG7RevfcvuBmtJ4hzT2xVHXI7tbZw2AAAAAAD9////AcbZAwAAAAAAFgAUrNrrQ8SyPR8FeUFDMRk4smzOZJAAAAAAAAEA6gIAAAAAAQF3OeuQFbDYPSSJNwOuN+0smr875L1m3LoB0aIH0oMLxAEAAAAA/f///wLy6QMAAAAAACIAIBgArSHArzycsaZlFrFOm9DbQmBNedBp0w0ggcQKGsO7lc+AAAAAAAAWABSI6DoyERn1mTmJ/2KJvwoVnMPLVwJHMEQCIDPYQ08u2HAyMRdVzOOrTnno2n7aejmI8FOt+vjLcod1AiBZX/5MtbhmDJhpAuX97oR1ykQ+6u+9MXnmPv+kQOOJugEhAhZn9mhi+YiIXg8iGDDow0LNweV9JttNQBph63COdGWKIpUeACICAgXjitZsueLfcTxY0+RtXwSihshX/ymJ/FO9n+DnKR61RzBEAiByuS4i968EBC18TUd2d/xRdhAnwCim8ggbicgC2bqulQIgRHMH20I1hH0tsL/cFdH9xzliZ9zPOhrNgqy2sGW3TWwBAAA=")

mypubkey2 = ecc.ECPrivkey(MYPRIVKEY2).get_public_key_bytes()
assert mypubkey2.hex() in PUBKEYS

txin = SWEEP_TX.inputs()[0]
txin.script_type = 'p2wsh'
txin.pubkeys = [bytes.fromhex(pk) for pk in PUBKEYS]
txin.num_sig = 2

SWEEP_TX.sign({mypubkey2.hex(): (MYPRIVKEY2, True)})
print(str(SWEEP_TX))

@SomberNight
Copy link
Member

@ondra-novak Here is a PSBT signed by my key (so which has 1 sig for the 2of2 multisig input):

cHNidP8BAFICAAAAAf+OI1gJeNujSQITYXZlU3k9mn+7q+ZqAHTT5xpYvOsqAgAAAAD9////ATf1/wAAAAAAFgAUY33fZ5OOE5WVQtUQoDHPeXffu+wAAAAAAAEA/akBAgAAAAABAmd9zY2Mqh3XxWGO4EGj09QPNN7UDAkTN9UVI3z6Bo45AAAAAAD+////I/yloU6ZzxHk8g7jmPESVuwakfvzhYk5Eyw5MwFIkUYAAAAAAP7///8DuAN2AAAAAAAWABT42PQaLW3f7i6HjRO7GeU9nNBKd////wAAAAAAIgAgussHfX4YQVZ1cDXDJsAZPeeCZ4s08saaq0QS/Hl0IuL///8AAAAAACIAIO4tqFfo9p+XTWSR4IOtjb3mCnt3+EDqtyLpUHq9/GQcAkcwRAIgA1HRr1qtZAlk9kWKqoG9f/gBZgNO1xSGC+xaXapX1JQCIDJsmjuVrORqgvgYbBOYLAcIxATdxxywV/rkdfa1o8t4ASED+u/mBsYXUOg+cZfbxY2su/xp5ujWWEDGbTdzwj6PBokCRzBEAiByLG+03St+bb6T3jQAkvcasmbMKD7KpwncwuN5rhf78gIgYsh4ZC9wRhDIulfWmaHevWdB6jLHFLEeRQEBZH3zdtwBIQPUOD+OlMQb3qDvRVa+1sBfFNDJUCMUQLx+wkQECL6w80RuCgAiAgMI7L02nELzzY0Gy+3XVN+iwkyKS8p4oOgk+cOF2bjaUkcwRAIgDm2btm2d6o0WxZhWPyLixUD+w95VaMVxeIjVFPVUTCsCIDOG3dLDxqjZaJwosZdw8GROF4p6D/wq4P67BZwJQypAAQAA

You should load this into a wallet that supports signing PSBTs and sign with your private key (corresponding to the pubkey 03d82db36b7b896077ab0d2b8165a3517a1ee363aa9e9f7bfa2fcfa14ccc81ef03).
Unfortunately Electrum (the GUI) currently does not support spending from an imported multisig address (only from HD multisig), so if you want to use Electrum, you need to run a bit of python code.

Check the below snippet I wrote for you, that should be run in a python interpreter.
You should substitute in your private key on the line MYPRIVKEY2 = bytes.fromhex("XXXXXTODOXXXXX").

from electrum.bitcoin import script_to_p2wsh
from electrum.transaction import multisig_script, tx_from_any, TxOutpoint, PartialTxInput, PartialTxOutput, PartialTransaction
from electrum import constants, ecc


PUBKEYS = sorted(["03d82db36b7b896077ab0d2b8165a3517a1ee363aa9e9f7bfa2fcfa14ccc81ef03", "0308ecbd369c42f3cd8d06cbedd754dfa2c24c8a4bca78a0e824f9c385d9b8da52"])
FUNDING_TX_HEX = "02000000000102677dcd8d8caa1dd7c5618ee041a3d3d40f34ded40c091337d515237cfa068e390000000000feffffff23fca5a14e99cf11e4f20ee398f11256ec1a91fbf3858939132c3933014891460000000000feffffff03b803760000000000160014f8d8f41a2d6ddfee2e878d13bb19e53d9cd04a77ffffff0000000000220020bacb077d7e184156757035c326c0193de782678b34f2c69aab4412fc797422e2ffffff0000000000220020ee2da857e8f69f974d6491e083ad8dbde60a7b77f840eab722e9507abdfc641c0247304402200351d1af5aad640964f6458aaa81bd7ff80166034ed714860bec5a5daa57d4940220326c9a3b95ace46a82f8186c13982c0708c404ddc71cb057fae475f6b5a3cb78012103faefe606c61750e83e7197dbc58dacbbfc69e6e8d65840c66d3773c23e8f0689024730440220722c6fb4dd2b7e6dbe93de340092f71ab266cc283ecaa709dcc2e379ae17fbf2022062c878642f704610c8ba57d699a1debd6741ea32c714b11e450101647df376dc012103d4383f8e94c41bdea0ef4556bed6c05f14d0c950231440bc7ec2440408beb0f3446e0a00"
FUNDING_OUTIDX = 2
MYPRIVKEY2 = bytes.fromhex("XXXXXTODOXXXXX")
SWEEP_TX = tx_from_any("cHNidP8BAFICAAAAAf+OI1gJeNujSQITYXZlU3k9mn+7q+ZqAHTT5xpYvOsqAgAAAAD9////ATf1/wAAAAAAFgAUY33fZ5OOE5WVQtUQoDHPeXffu+wAAAAAAAEA/akBAgAAAAABAmd9zY2Mqh3XxWGO4EGj09QPNN7UDAkTN9UVI3z6Bo45AAAAAAD+////I/yloU6ZzxHk8g7jmPESVuwakfvzhYk5Eyw5MwFIkUYAAAAAAP7///8DuAN2AAAAAAAWABT42PQaLW3f7i6HjRO7GeU9nNBKd////wAAAAAAIgAgussHfX4YQVZ1cDXDJsAZPeeCZ4s08saaq0QS/Hl0IuL///8AAAAAACIAIO4tqFfo9p+XTWSR4IOtjb3mCnt3+EDqtyLpUHq9/GQcAkcwRAIgA1HRr1qtZAlk9kWKqoG9f/gBZgNO1xSGC+xaXapX1JQCIDJsmjuVrORqgvgYbBOYLAcIxATdxxywV/rkdfa1o8t4ASED+u/mBsYXUOg+cZfbxY2su/xp5ujWWEDGbTdzwj6PBokCRzBEAiByLG+03St+bb6T3jQAkvcasmbMKD7KpwncwuN5rhf78gIgYsh4ZC9wRhDIulfWmaHevWdB6jLHFLEeRQEBZH3zdtwBIQPUOD+OlMQb3qDvRVa+1sBfFNDJUCMUQLx+wkQECL6w80RuCgAiAgMI7L02nELzzY0Gy+3XVN+iwkyKS8p4oOgk+cOF2bjaUkcwRAIgDm2btm2d6o0WxZhWPyLixUD+w95VaMVxeIjVFPVUTCsCIDOG3dLDxqjZaJwosZdw8GROF4p6D/wq4P67BZwJQypAAQAA")

mypubkey2 = ecc.ECPrivkey(MYPRIVKEY2).get_public_key_bytes()
assert mypubkey2.hex() in PUBKEYS

txin = SWEEP_TX.inputs()[0]
txin.script_type = 'p2wsh'
txin.pubkeys = [bytes.fromhex(pk) for pk in PUBKEYS]
txin.num_sig = 2

SWEEP_TX.sign({mypubkey2.hex(): (MYPRIVKEY2, True)})
print(str(SWEEP_TX))

Let me know if you need further help or if it worked.

@ondra-novak
Copy link
Author

Works! Transaction is on the way. Thank you very much!

@SomberNight
Copy link
Member

Great. Sorry for the trouble and thanks for the report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐞 lightning ⚡ topic-wallet 👛 related to wallet.py, or maybe address_synchronizer.py/coinchooser.py
Projects
None yet
Development

No branches or pull requests

3 participants
@ondra-novak @SomberNight and others