trezor-firmware icon indicating copy to clipboard operation
trezor-firmware copied to clipboard

Investigate CSV (CHECKSEQUENCEVERIFY) usage

Open prusnak opened this issue 5 years ago • 9 comments

Some wallets (such as Blockstream Green) use CSV (CHECKSEQUENCEVERIFY) in their scripts. Let's ask them how their scripts look like and see how we can integrate this into our protobuf messages.

prusnak avatar Nov 13 '19 19:11 prusnak

@romanz Can you help us with finding the right person to document how exactly does the scripts in Blockstream Green look like? (We don't like signing arbitrary scripts, so we have to understand the structure first and "teach" Trezor how to build transactions like these).

prusnak avatar Nov 13 '19 19:11 prusnak

Green wallet is using libwally-core for generating the Bitcoin scripts for CSV-based multisig. There are currently two types of such scripts (where main key is controlled by the server and recovery keys are controlled by the user):

  1. (2-of-2) or (1-of-2 after CSV):
OP_DEPTH OP_1SUB
OP_IF
  # The stack contains the main and and recovery signatures.
  # Check the main signature then fall through to check the recovery.
  <main_pubkey> OP_CHECKSIGVERIFY
OP_ELSE
  # The stack contains only the recovery signature.
  # Check the CSV time has expired then fall though as above.
  <csv_blocks> OP_CHECKSEQUENCEVERIFY OP_DROP
OP_ENDIF
# Check the recovery signature
<recovery_pubkey> OP_CHECKSIG
  1. (2-of-3) or (1-of-2 after CSV)
OP_DEPTH OP_1SUB OP_1SUB
OP_IF
  # The stack contains 3 items, a dummy push for the off-by-one bug
  # in OP_CHECKMULTISIG, and any 2 of the 3 signatures.
  OP_2 <main_pubkey>
OP_ELSE
  # The stack contains a dummy push as above, and either of the
  # recovery signatures.
  <csv_blocks> OP_CHECKSEQUENCEVERIFY OP_DROP
  # Note OP_0 is a dummy pubkey that can't match any signature. This
  # allows us to share the final OP_3 OP_CHECKMULTISIGVERIFY case
  # thus reducing the size of the script.
  OP_1 OP_0
OP_ENDIF
# Shared code to check the signatures provided
<recovery_pubkey_1> <recovery_pubkey_2> OP_3 OP_CHECKMULTISIG

There is a proof-of-concept trezor-firmware branch that allows the user to create p2sh & bech32 addresses controlled by the first type of CSV-based multisig script above and spend from them. I've added a csv field to the multisig protobuf definition which causes the code to use CSV-based multisig script (instead of the OP_CHECKMULTISIG "standard" one). Although it's a bit "hacky", it seems to work as intended (see integration tests for Bitcoin p2sh & bech32 addresses and the following Testnet transaction for cooperative spending example from 2-of-2 CSV-based multisig address).

CC: @greenaddress

romanz avatar Nov 13 '19 21:11 romanz

Thanks for the code! We'll have a look at it

prusnak avatar Nov 15 '19 11:11 prusnak

I agree it makes sense to do this, but we need to refactor the wallet.sign_tx app first: https://github.com/trezor/trezor-firmware/issues/617

prusnak avatar Dec 16 '19 17:12 prusnak

Sounds good, thanks for the update!

romanz avatar Dec 16 '19 21:12 romanz

Updated and rebased csv-multisig branch over the latest master.

romanz avatar Jan 18 '20 10:01 romanz

Rebased over latest master and force-pushed https://github.com/trezor/trezor-firmware/commit/95979fc9ff7fe312e80280d5f75a199153e640b7.

romanz avatar Feb 13 '20 09:02 romanz

Related to #416.

tsusanka avatar Aug 03 '20 10:08 tsusanka

Also the miniscript policy for a 2-of-2 that turns into a 1-of-2 after 90 days: and_v(v:pk(key_user),or_d(pk(key_service),older(12960))) (from: https://bitcoin.sipa.be/miniscript/ )

georgantas avatar May 19 '22 03:05 georgantas