Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: cedricfung on March 02, 2023, 05:16:26 AM



Title: P2WSH Multisig and Timelock question
Post by: cedricfung on March 02, 2023, 05:16:26 AM
I'm working on a wallet solution to use 2/3 multisig with timelock.

A and B can spend the UTXO together before the timelock, but C can only spend the UTXO with A or B after the timelock expires.

So I wrote the script as below, is it correctly implemented as the requirement?

Code:
OP_IF
2
OP_ELSE
4194311 OP_CHECKSEQUENCEVERIFY OP_DROP
key_C OP_CHECKSIGVERIFY
1
OP_ENDIF
key_A key_B 2 OP_CHECKMULTISIG

Thank you


Title: Re: P2WSH Multisig and Timelock question
Post by: pooya87 on March 02, 2023, 11:49:04 AM
Looks correct to me but you can always test things like this on the TestNet (https://en.bitcoin.it/wiki/Testnet) to be more sure, specially when it comes to setting the time value in the timelock.
Also what you called "OP_PUSHNUM_2" and "OP_PUSHNUM_1" should be OP_2 and OP_1 respectively with 0x52 and 0x51 as their byte representations.


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on March 02, 2023, 01:02:44 PM
Thank you, the bitcoin-cli script ASM is

Code:
OP_IF 2 OP_ELSE 4194311 OP_CHECKSEQUENCEVERIFY OP_DROP key_C OP_CHECKSIGVERIFY 1 OP_ENDIF key_A key_B 2 OP_CHECKMULTISIG

I used the number 2 and 1, not OP_2 or OP_1, as I understand from the tutorial https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/10_4_Scripting_a_Multisig.md#create-a-raw-multisig

According to this tutorial https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/11_3_Using_CSV_in_Scripts.md#create-a-csv-relative-time

I calculated the relative lock time of 1 hour as below

Code:
nSequence = (1 << 22) | (3600 >> 9)
=> 4194311

But one thing confused me is the miniscript sample https://bitcoin.sipa.be/miniscript/

For 90 days, it uses 12960 in miniscript, and the compiled sequence is a032, that's too small a number.


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on March 02, 2023, 01:26:02 PM
For the nSequence value in the miniscript example, it's using relative block number instead of time, that's why it's such a small number.


Title: Re: P2WSH Multisig and Timelock question
Post by: Jason Brendon on March 13, 2023, 06:39:32 AM
very impressive.
But can people tell all the spend conditions from the blockchain?


Title: Re: P2WSH Multisig and Timelock question
Post by: Jason Brendon on March 14, 2023, 06:44:38 AM
very impressive.
But can people tell all the spend conditions from the blockchain?

For P2WSH and P2SH, everyone will know spend condition/redeem script after the coin has been spent. If you don't want that, consider P2TR instead.

taproot? what wallet can send coins from taproot addresses to others?


Title: Re: P2WSH Multisig and Timelock question
Post by: NotATether on March 14, 2023, 07:20:30 AM
In the timelock branch:

Code:
key_C OP_CHECKSIGVERIFY
1
OP_ENDIF
key_A key_B 2 OP_CHECKMULTISIG

You would have to put C's signature in the last cosigner of the output in order for the script to work properly, correct?

Other than that, this script looks well-formed to me.

taproot? what wallet can send coins from taproot addresses to others?

Sparrow Wallet can do that. I think maybe Bitcoin Core can do that now too, because Ordinals claim to use that feature. And it's always possible to construct Taproot transactions with spend paths by hand if you are sufficiently masochist  :)



Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on March 14, 2023, 09:25:35 AM
In the timelock branch:

Code:
key_C OP_CHECKSIGVERIFY
1
OP_ENDIF
key_A key_B 2 OP_CHECKMULTISIG

You would have to put C's signature in the last cosigner of the output in order for the script to work properly, correct?

Yes, when timelock expired, to spend the output with key_C, the script is like

Code:
<empty> sig_A sig_C <empty> WITNESS

Is this correct?


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on March 14, 2023, 12:16:11 PM
I just checked my Bitcoin Core (v24.0.1) and it has Taproot support which can be generated on tab "Receive" and choose "Bech32m (Taproot)" on drop-down list. But for custom scripting, i expect you'll need to use CLI and create script manually. And for information purpose, Wasabi wallet also support Taproot although IIRC it lacks some feature for power user.

I think no wallets support real custom scripting yet, at least Bitcoin Core is only able to watch those custom script address, can't spend from them.


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on March 14, 2023, 02:08:25 PM
I just checked my Bitcoin Core (v24.0.1) and it has Taproot support which can be generated on tab "Receive" and choose "Bech32m (Taproot)" on drop-down list. But for custom scripting, i expect you'll need to use CLI and create script manually. And for information purpose, Wasabi wallet also support Taproot although IIRC it lacks some feature for power user.

I think no wallets support real custom scripting yet, at least Bitcoin Core is only able to watch those custom script address, can't spend from them.

But since Bitcoin Core support Output Descriptors[1], spending should be possible[2] if you know how to convert the script into descriptors. Although it's still not real custom scripting since AFAIK descriptors due to limited support of opcodes.

[1] https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md (https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md)
[2] https://bitcoin.stackexchange.com/a/99541 (https://bitcoin.stackexchange.com/a/99541)

Bitcoin Core supports custom script with output descriptors, that's the miniscript from blockstream, it has full capability to support all popular opcodes. But still, most of output descriptors support in Bitcoin Core are limited to watch only, the core devs have some ongoing issues to solve this.

https://github.com/bitcoin/bitcoin/pull/24149 This PR makes miniscript completely solvable in Bitcoin Core, merged last month, and it's just the miniscript support in the code level, not full bitcoin-cli support yet, maybe in a few months.


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on May 28, 2023, 12:04:15 PM
Now it looks like full descriptors support arrived with Bitcoin Core 25.0 https://github.com/bitcoin/bitcoin/releases/tag/v25.0

So now I'm going to use this descriptor script to achieve the same goal.

Code:
wsh(thresh(2,pk(A),s:pk(B),sj:and_v(v:pk(C),n:older(1728))))


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on May 28, 2023, 12:06:40 PM
Now it looks like full descriptors support arrived with Bitcoin Core 25.0 https://github.com/bitcoin/bitcoin/releases/tag/v25.0

So now I'm going to use this descriptor script to achieve the same goal.

Code:
wsh(thresh(2,pk(A),s:pk(B),sj:and_v(v:pk(C),n:older(1728))))

This produces the asm

Code:
A OP_CHECKSIG OP_SWAP 
B OP_CHECKSIG OP_ADD OP_SWAP OP_SIZE OP_0NOTEQUAL
OP_IF
C OP_CHECKSIGVERIFY 1728 OP_CHECKSEQUENCEVERIFY OP_0NOTEQUAL
OP_ENDIF
OP_ADD 2 OP_EQUAL


Title: Re: P2WSH Multisig and Timelock question
Post by: Jason Brendon on June 21, 2023, 03:42:16 AM
Now it looks like full descriptors support arrived with Bitcoin Core 25.0 https://github.com/bitcoin/bitcoin/releases/tag/v25.0

So now I'm going to use this descriptor script to achieve the same goal.

Code:
wsh(thresh(2,pk(A),s:pk(B),sj:and_v(v:pk(C),n:older(1728))))

This produces the asm

Code:
A OP_CHECKSIG OP_SWAP 
B OP_CHECKSIG OP_ADD OP_SWAP OP_SIZE OP_0NOTEQUAL
OP_IF
C OP_CHECKSIGVERIFY 1728 OP_CHECKSEQUENCEVERIFY OP_0NOTEQUAL
OP_ENDIF
OP_ADD 2 OP_EQUAL

Are you able to spend the coins by btc core? The cli seems pretty cumbersome to use.


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on July 11, 2023, 08:50:11 AM
Now it looks like full descriptors support arrived with Bitcoin Core 25.0 https://github.com/bitcoin/bitcoin/releases/tag/v25.0

So now I'm going to use this descriptor script to achieve the same goal.

Code:
wsh(thresh(2,pk(A),s:pk(B),sj:and_v(v:pk(C),n:older(1728))))

This produces the asm

Code:
A OP_CHECKSIG OP_SWAP 
B OP_CHECKSIG OP_ADD OP_SWAP OP_SIZE OP_0NOTEQUAL
OP_IF
C OP_CHECKSIGVERIFY 1728 OP_CHECKSEQUENCEVERIFY OP_0NOTEQUAL
OP_ENDIF
OP_ADD 2 OP_EQUAL

Are you able to spend the coins by btc core? The cli seems pretty cumbersome to use.

After changed to this miniscript solution, I'm able to spend the coins with both Bitcoin Core cli and Ledger Nano X.


Title: Re: P2WSH Multisig and Timelock question
Post by: Supporters00 on July 11, 2023, 06:02:37 PM
I'm working on a wallet solution to use 2/3 multisig with timelock.

A and B can spend the UTXO together before the timelock, but C can only spend the UTXO with A or B after the timelock expires.

So I wrote the script as below, is it correctly implemented as the requirement?

Code:
OP_IF
2
OP_ELSE
4194311 OP_CHECKSEQUENCEVERIFY OP_DROP
key_C OP_CHECKSIGVERIFY
1
OP_ENDIF
key_A key_B 2 OP_CHECKMULTISIG

Thank you





Based on your description, it seems like you want to create a script that enforces a 2-of-3 multisig with a timelock. A and B can spend the UTXO together before the timelock, but after the timelock expires, C can spend the UTXO with either A or B.

The script you provided is almost correct, but there's a small mistake. Here's the corrected version:


Code:
OP_IF
    2
OP_ELSE
    <timelock> OP_CHECKSEQUENCEVERIFY OP_DROP
    <key_C> OP_CHECKSIGVERIFY
OP_ENDIF
<key_A> <key_B> 2 OP_CHECKMULTISIG


In the script above, replace <timelock> with the desired timelock value (in blocks or seconds) and <key_A>, <key_B>, and <key_C> with the respective public keys or their corresponding script hashes.

The modified script enforces the following conditions:

If the condition inside OP_IF is true (timelock has not expired):
The top stack element should be the number 2 (indicating a 2-of-2 multisig condition between A and B).
If the condition inside OP_ELSE is true (timelock has expired):
The top stack element should be the timelock value.
C's public key or script hash should successfully verify using OP_CHECKSIGVERIFY.
Finally, <key_A>, <key_B>, and the number 2 are used for the final 2-of-2 multisig check.
Remember to provide the actual values for <timelock>, <key_A>, <key_B>, and <key_C> when implementing this script in a real-world scenario .


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on July 13, 2023, 08:09:26 AM
Based on your description, it seems like you want to create a script that enforces a 2-of-3 multisig with a timelock. A and B can spend the UTXO together before the timelock, but after the timelock expires, C can spend the UTXO with either A or B.

The script you provided is almost correct, but there's a small mistake. Here's the corrected version:


Code:
OP_IF
    2
OP_ELSE
    <timelock> OP_CHECKSEQUENCEVERIFY OP_DROP
    <key_C> OP_CHECKSIGVERIFY
OP_ENDIF
<key_A> <key_B> 2 OP_CHECKMULTISIG


In the script above, replace <timelock> with the desired timelock value (in blocks or seconds) and <key_A>, <key_B>, and <key_C> with the respective public keys or their corresponding script hashes.

The modified script enforces the following conditions:

If the condition inside OP_IF is true (timelock has not expired):
The top stack element should be the number 2 (indicating a 2-of-2 multisig condition between A and B).
If the condition inside OP_ELSE is true (timelock has expired):
The top stack element should be the timelock value.
C's public key or script hash should successfully verify using OP_CHECKSIGVERIFY.
Finally, <key_A>, <key_B>, and the number 2 are used for the final 2-of-2 multisig check.
Remember to provide the actual values for <timelock>, <key_A>, <key_B>, and <key_C> when implementing this script in a real-world scenario .

Hi, thank you for suggestion. But I don't understand how the OP_ELSE branch makes key_C and key_A enough to unlock the script? Because from your explanation, key_C should verify, then both key_A and key_B should do the 2-of-2 multisig check.

And I also don't get how is this 2-of-2 multisig produced, since the OP_ELSE branch doesn't provide a threshold number for the OP_CHECKMULTISIG. That's why I provide the number 1 before ENDIF to make 1 key_A key_B 2 CHECKMULTISIG.

BTW, I have changed the script to miniscript, any suggestions to this?

Code:
wsh(thresh(2,pk(A),s:pk(B),sj:and_v(v:pk(C),n:older(1728))))

A OP_CHECKSIG OP_SWAP
B OP_CHECKSIG OP_ADD OP_SWAP OP_SIZE OP_0NOTEQUAL
OP_IF
C OP_CHECKSIGVERIFY 1728 OP_CHECKSEQUENCEVERIFY OP_0NOTEQUAL
OP_ENDIF
OP_ADD 2 OP_EQUAL


Title: Re: P2WSH Multisig and Timelock question
Post by: NotATether on July 13, 2023, 09:06:53 AM
Based on your description, it seems like you want to create a script that enforces a 2-of-3 multisig with a timelock. A and B can spend the UTXO together before the timelock, but after the timelock expires, C can spend the UTXO with either A or B.

The script you provided is almost correct, but there's a small mistake. Here's the corrected version:


Code:
OP_IF
    2
OP_ELSE
    <timelock> OP_CHECKSEQUENCEVERIFY OP_DROP
    <key_C> OP_CHECKSIGVERIFY
OP_ENDIF
<key_A> <key_B> 2 OP_CHECKMULTISIG


In the script above, replace <timelock> with the desired timelock value (in blocks or seconds) and <key_A>, <key_B>, and <key_C> with the respective public keys or their corresponding script hashes.

The modified script enforces the following conditions:

If the condition inside OP_IF is true (timelock has not expired):
The top stack element should be the number 2 (indicating a 2-of-2 multisig condition between A and B).
If the condition inside OP_ELSE is true (timelock has expired):
The top stack element should be the timelock value.
C's public key or script hash should successfully verify using OP_CHECKSIGVERIFY.
Finally, <key_A>, <key_B>, and the number 2 are used for the final 2-of-2 multisig check.
Remember to provide the actual values for <timelock>, <key_A>, <key_B>, and <key_C> when implementing this script in a real-world scenario .

Hi, thank you for suggestion. But I don't understand how the OP_ELSE branch makes key_C and key_A enough to unlock the script? Because from your explanation, key_C should verify, then both key_A and key_B should do the 2-of-2 multisig check.

And I also don't get how is this 2-of-2 multisig produced, since the OP_ELSE branch doesn't provide a threshold number for the OP_CHECKMULTISIG. That's why I provide the number 1 before ENDIF to make 1 key_A key_B 2 CHECKMULTISIG.

In the ELSE branch, the sequence number is being verified, and if that's correct, then key_C is verified (and should be the top-most item on the witness data stack). If key_C is verified successfully, then OP_CHECKSIGVERIFY pushes True, which is actually represented as 1 according to  https://en.bitcoin.it/wiki/Script#Constants .

So this 1 value means that only one of key_A or key_B need to be present below key_C in the stack, in order for OP_CHECKMULTISIG to succeed. In other words, the ELSE branch converts the signing into Verify key_C + 1-of-2 multisig, as opposed to 2-of-2 multisig (without Key_C) in the IF branch.

I hope you understand it now.


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on July 14, 2023, 02:57:09 AM
In the ELSE branch, the sequence number is being verified, and if that's correct, then key_C is verified (and should be the top-most item on the witness data stack). If key_C is verified successfully, then OP_CHECKSIGVERIFY pushes True, which is actually represented as 1 according to  https://en.bitcoin.it/wiki/Script#Constants .

So this 1 value means that only one of key_A or key_B need to be present below key_C in the stack, in order for OP_CHECKMULTISIG to succeed. In other words, the ELSE branch converts the signing into Verify key_C + 1-of-2 multisig, as opposed to 2-of-2 multisig (without Key_C) in the IF branch.

I hope you understand it now.

Thank you! Any comments on the miniscript version?


Title: Re: P2WSH Multisig and Timelock question
Post by: NotATether on July 14, 2023, 11:11:26 AM
Thank you! Any comments on the miniscript version?

I don't fully know Miniscript so there's not much I can say about the one-line version, but if the script immediately below it is the result of compiling the Miniscript to Script, then I must say it's significantly larger than the original script, and so I can't advise using it if this is going to be used hundreds of times (you, or the user who is making it, will have to pay extra fees per tx).


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on July 14, 2023, 12:21:33 PM
Thank you! Any comments on the miniscript version?

I don't fully know Miniscript so there's not much I can say about the one-line version, but if the script immediately below it is the result of compiling the Miniscript to Script, then I must say it's significantly larger than the original script, and so I can't advise using it if this is going to be used hundreds of times (you, or the user who is making it, will have to pay extra fees per tx).

I agree it's more expensive, but miniscript is the only option to get wallets support.


Title: Re: P2WSH Multisig and Timelock question
Post by: Jason Brendon on July 21, 2023, 06:30:47 AM

Quote

Sparrow Wallet can do that. I think maybe Bitcoin Core can do that now too, because Ordinals claim to use that feature. And it's always possible to construct Taproot transactions with spend paths by hand if you are sufficiently masochist  :)


I tried. Sparrow cannot spend from a taproot address. it can only create taproot addresses.


Title: Re: P2WSH Multisig and Timelock question
Post by: Rickorick on July 24, 2023, 06:25:38 PM
Sorry to hijack but can anyone help with spending a transaction from a time lock address???

I accidentally made the time lock 7140000 instead of 714000 and that means I have to wait 120 years to spend the coins. Please can anyone help????


Title: Re: P2WSH Multisig and Timelock question
Post by: pooya87 on July 25, 2023, 03:45:56 AM
Sorry to hijack but can anyone help with spending a transaction from a time lock address???

I accidentally made the time lock 7140000 instead of 714000 and that means I have to wait 120 years to spend the coins. Please can anyone help????
If you created the script correctly then there is no way to spend these coins and nobody can help. The Bitcoin protocol is solid and will not allow these coins to move until block #7140000
Otherwise the only chance you have is if you made a mistake (wrong locktime value, using a branch that could be skipped, etc.) in which case you can post your full redeem script (like the ones you see in this topic) containing the OP codes, the locktime value and your public key here for people to see if there is any chance.


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on July 25, 2023, 07:31:06 AM
Sorry to hijack but can anyone help with spending a transaction from a time lock address???

I accidentally made the time lock 7140000 instead of 714000 and that means I have to wait 120 years to spend the coins. Please can anyone help????
If you created the script correctly then there is no way to spend these coins and nobody can help. The Bitcoin protocol is solid and will not allow these coins to move until block #7140000
Otherwise the only chance you have is if you made a mistake (wrong locktime value, using a branch that could be skipped, etc.) in which case you can post your full redeem script (like the ones you see in this topic) containing the OP codes, the locktime value and your public key here for people to see if there is any chance.

The maximum timelock allowed in Bitcoin is 0xffff, about 455 days. So you can't make a timelock of 120 years.


Title: Re: P2WSH Multisig and Timelock question
Post by: ranochigo on July 25, 2023, 08:07:23 AM
The maximum timelock allowed in Bitcoin is 0xffff, about 455 days. So you can't make a timelock of 120 years.
OP_CLTV is different from OP_CSV (absolute vs relative). It allows for the locking of Bitcoin to be evaluated either by unix time or block height, the latter for which is up to >9000 years while the former is until 2106.


Title: Re: P2WSH Multisig and Timelock question
Post by: o_e_l_e_o on July 25, 2023, 09:17:55 AM
This is almost certainly the same address which another used claimed to have created in this thread:
https://bitcointalk.org/index.php?topic=5455368.msg62364885#msg62364885
Archive - https://ninjastic.space/post/62364375

It seems that a scammer might be selling the private key to this timelocked address to multiple users who then realize they are unable to claim the coins and come here looking for help.


Title: Re: P2WSH Multisig and Timelock question
Post by: cedricfung on July 26, 2023, 06:09:21 AM
The maximum timelock allowed in Bitcoin is 0xffff, about 455 days. So you can't make a timelock of 120 years.
OP_CLTV is different from OP_CSV (absolute vs relative). It allows for the locking of Bitcoin to be evaluated either by unix time or block height, the latter for which is up to >9000 years while the former is until 2106.

You are right, forgot about the absolute timelock value.