πŸ₯• Create a multisig with taproot and spend from it using BDK πŸ₯•

Overview

Multisig & carrots

This repository contains all the code to build a taproot multisig with your friends, and to spend from it. It's been used first to do the BDK workshop in the Azores Unconference, where we created this transaction: https://blockstream.info/testnet/tx/d40c55286933dfc2debb6b34832070401db33f53c78143bfb48717b79d237bdf?expand. You can find a transcript of the experiment here: https://twitter.com/michaelfolkson/status/1573644913224425473?s=20&t=NXMkPwrfZRvrUdPb5pBA2g

You can use this same code to re-create this workshop at some conference. You can use it to organize a Taproot night with your friends. You can use it by yourself to learn how BDK works. You can use it however you want. :)

The details

The experiment is composed of various participants, which will hold private keys and sign the transaction, and one coordinator, whose job is to, well, coordinate: creating the descriptor, creating the transaction, merging the signatures together and broadcasting the transaction.

At each step, I suggest commenting the whole file, and then uncommenting it, line by line, while you read it. If some parts are not clear, you are encouraged to add dbg!() and println!() statements, and run the code to see what happens. Don't be scared of experimenting :)

Some data needs to be exchanged between the coordinator and the participants (public keys, descriptor, PSBTs). In the real experiment we chose to use telegram, as it works well on desktop, but there are some obvious privacy concerns. Find a messaging app that works for you, or, if you're a real hacker, build a web page for submitting the data.

This article will give you a brief introduction to Taproot descriptors: https://bitcoinops.org/en/preparing-for-taproot/#taproot-descriptors

In this example, we put a dummy key in the key spend path (spending with just a key is too easy for us 😁 ), and two different policies in the script spend path:

  1. You can spend immediately if at least half of the participants sign
  2. You can spend after 100 with a recovery key - just in case too many participants lose their keys :)

The steps

The experiment is composed of 5 steps:

  1. Participants generate private keys, and share the public ones
  2. Coordinator generates the descriptor
  3. Coordinator sends money to the descriptor, then creates a PSBT for spending
  4. Participants sign the PSBT
  5. Coordinator merges the signatures together and broadcasts

Step 1: generating the keys (everyone)

This will create a WIF key, print the public one to stdout, and write the private one to key.txt. Make sure not to delete key.txt!

Run with:

cargo run --bin generate_keys

Step 2: generating the descriptor (coordinator only)

Only the coordinator needs to run this step. After gathering all the participants' public keys, insert them in the "keys" vector. The descriptor will be printed to stdout. Send it to the group, as you'll need it for the next steps.

Run with:

cargo run --bin generate_descriptor

Step 3: creating a transaction spending the funds (coordinator only)

Only the coordinator needs to run this step. You should NOT run this file all at once - instead, uncomment Step 1 and 2, insert the descriptor obtained in step 2 where indicated, run the file and send some testnet coins to the address displayed. Only then uncomment the rest. The code will print a PSBT - send it to the group, you'll need it for the next step

Run with:

cargo run --bin create_psbt

Step 4: signing the transaction

In this step everyone will sign the PSBT obtained in step 3. Make sure that you still have the key.txt file, remove the TODOs and insert your descriptor and your PSBT instead. The file will print to stdout the signed PSBT - send it to the coordinator.

Run with:

cargo run --bin sign_transaction

Step 5: merging the signatures together, broadcasting (coordinator only)

Last step! The coordinator will gather everyone's transactions, insert them in the file, which will combine them all together and try to finalize and extract a bitcoin transaction. If all goes well, the transaction will be extracted and broadcasted πŸŽ‰

cargo run --bin combine_psbts

Going further

If you're up for a challenge, try to:

  1. Use BIP32 keys instead of WIF keys
  2. Spend using the recovery path (you need to wait 100 blocks first!)
  3. Sync and broadcast the transaction using a different backend, such as Electrum or Bitcoin Core (we use esplora both in create_psbt and combine_psbts)
  4. Spend using the key spend path (hint: you need to change the descriptor a bit, or find a way to break secp256k1)
You might also like...
Ethereum (and Ethereum like) indexer using P2P message to fetch blocks and transactions

Ethereum P2P indexer This project is an indexer for Ethereum and Ethereum forks. It takes advantage of the ETH (Ethereum Wire Protocol) to fetch block

shavee is a Program to automatically decrypt and mount ZFS datasets using Yubikey HMAC as 2FA or any USB drive with support for PAM to auto mount home directories.

shavee is a simple program to decrypt and mount encrypted ZFS user home directories at login using Yubikey HMAC or a Simple USB drive as 2FA written in rust.

A prototype project integrating jni rust into Kotlin and using protobuf to make them work together

KotlinRustProto a prototype project integrating jni rust into Kotlin and using protobuf to make them work together How to start add a RPC call in Droi

Port path module (and tests) of nodejs to rust using the same algorithms.

rusty_nodejs_path Port path module (and tests) of nodejs to rust using the same algorithms. crates.io Documents Progress posix path.basename(path[, ex

Nym provides strong network-level privacy against sophisticated end-to-end attackers, and anonymous transactions using blinded, re-randomizable, decentralized credentials.

The Nym Privacy Platform The platform is composed of multiple Rust crates. Top-level executable binary crates include: nym-mixnode - shuffles Sphinx p

An open source desktop wallet for nano and banano with end-to-end encrypted, on chain messaging using the dagchat protocol.
An open source desktop wallet for nano and banano with end-to-end encrypted, on chain messaging using the dagchat protocol.

An open source wallet with end-to-end encrypted, on chain messaging for nano and banano using the dagchat protocol.

Galleries of NFTs using Solana and Rust for contracts

About this Package created to simplify the process of parsing NFTs on Solana. It consists of: Package basic things like fetch all NFTs for specific wa

Thaler's Proofs, Args, and ZK Implemented in Rust using arkworks
Thaler's Proofs, Args, and ZK Implemented in Rust using arkworks

rthaler β€’ Dr. Thaler's book Proofs, Args, and ZK implemented in rust using the arkworks cryptographic rust toolset. Various Zero Knowledge Protocols a

Silent monero miner using xmrig and has 0% donation.

Note If this reprository is useful to you in in any shape or form please give it a star. Educational purposes only Don't use this project maliciously.

Comments
  • Policy paths

    Policy paths

    Hey, I tried to switch policy paths in your code and in modified code written by me (without taproot) and found out that changes have no effect whatsoever on finalization or signing.

    I am talking about this line

    https://github.com/danielabrozzoni/multisigs_and_carrots/blob/cb7bbd4ce044aca846c930087dc865bf04582af8/src/create_psbt.rs#L40

    may be you have some ideas @danielabrozzoni why it happens?

    opened by evd0kim 0
Owner
Daniela Brozzoni
Daniela Brozzoni
A quick create wizard to create and modify opinionated kustomize deployments.

kqc ?? ☸️ A quick create wizard to create and modify opinionated kustomize deployments. This tool should help to quickly create and build up kustomize

Daniel Jankowski 8 May 20, 2023
Zei is a library that provide tools to create and verify public transaction with confidential data.

#Zei: Findora's Cryptographic Library Zei is a library that provide tools to create and verify public transaction with confidential data. Support: Bas

Findora Foundation 0 Oct 23, 2022
Starknet Stack let's you easily create new Cairo Starknet chains with their own sequencers, provers and verifiers

Starknet Stack flowchart LR A("Client") ==>|"Starknet Transactions"| subGraph0["Sequencer"] subGraph0 -.->|"Blocks with txs"| 300319["Watcher prover

Lambdaclass 7 Jul 11, 2023
Create your personal token with rust smart contracts

Solana Rust Token ?? This application written Rust using Anchor βš“

Ritesh 6 Nov 22, 2022
MevWallet is a smart contract wallet that allows the user to capture MEV from Searchers, or create MEV on purpose.

MevWallet MevWallet is a smart contract wallet that allows the user to capture MEV from Searchers, or create MEV on purpose. This repo contains the so

Blunt Instruments 94 Jan 26, 2023
A template to create Rust-based Pure Data externals

Generate a Rust-based external for Pure Data This is a cargo generate template to create a Pure Data external written entirely in Rust. It uses pureda

Mads Kjeldgaard 6 May 1, 2024
Create a Stark prover & verifier from zero

stark-from-zero Create a Stark prover and verifier from zero, with Rust. Hopefully without external libraries. The point is to create a minimal versio

Lauri Peltonen 7 May 7, 2024
tool to create a relic export from network packets of a certain turn-based anime game

reliquary-archiver tool to create a relic export from network packets of a certain turn-based anime game json output format is based on the format of

IceDynamix 133 Jul 10, 2024
A simple and secure rust command-line tool to protect your text by encrypting and decrypting it using the robust AES-256 algorithm.

Secret Keeper A simple and secure command-line tool to protect your text by encrypting and decrypting it using the robust AES-256 algorithm. Built wit

Kunal Bagaria 9 May 11, 2023