Maximizing personal sovereignty and safety.

A complete guide to using M/N multisig wallets in Monero doesn’t yet exist since it’s very new. This guide aims to gather into one place all the information needed to use M/N multisig.

Multisig wallets are very important for people and organizations that need to store cryptocurrencies securely. They provide security against theft of private keys and redundancy in case of loss. Multisig wallets are an industry standard security practice used by most exchanges, web wallets, crypto funds, foundations, and other custodians of significant amounts of cryptocurrency.

This post is about Monero, but most people probably had their first encounter with multisig addresses from Bitcoin. Under the hood, Monero works very differently from Bitcoin, so the Monero developers had to come up with a new system to implement multisig. It can’t depend on the Bitcoin scripting language, and it has to play nice with the crypto systems that Monero uses to safeguard user privacy.

There have been two stages to Monero’s multisig launch. First, Monero introduced N/N and N-1/N multisig at the end of 2017, enabling multisig schemas like 2-of-2 and 2-of-3 wallets. Second, Monero introduced M/N wallets for arbitrary M less than N in late 2018. This includes wallet schemas like 3-of-5.

Let’s get started with initial setup of a Monero multisig wallet.

Monero Multisig Wallet Setup

Disclaimer: There was a bug in the M/N multisig implementation that sometimes prevents spending from M/N wallets. It was fixed after the latest release version of Monero (v0.13.0.4), so be sure to test your wallet workflow before storing significant funds with it. The process in this guide works reliably on the Monero master development branch.

Setting up a multisig wallet by hand in Monero is a tedious process because the participating wallets need to share several rounds of data with each other to create the multisig keys that will be used to see and sign transactions. Each of the three wallet types has its own setup process: N/N, N-1/N, and M/N. Out of those three, M/N is the most complex — setting up a 3-of-5 wallet takes 25 wallet operations. I found it easiest to automate the process to avoid mistakes and save time.

For any multisig setup, the Monero command line programs include a utility for generating wallets called monero-gen-trusted-multisig. If you want to generate all the participating multisig wallets on a single trusted machine, it gets the job done. It can be invoked as follows, setting scheme to be whatever you’d like to use:

$ monero-gen-trusted-multisig --scheme=3/5 --filename-base=wallet

If that doesn’t cover your use case, you’ll need to do a more involved setup. In this document, we’ll give a brief overview of the process for each type, but we’ll only go into detail for M/N wallets (N/N and N-1/N wallets already have a good guide).

The following are the commands that need to be run to generate a multisig wallet for each type. These commands can be run either at the command line through the monero-wallet-cli program or using the JSON-RPC server monero-wallet-rpc. Each command is run once for every participating wallet. Refer to the Monero Wallet RPC guide for which parameters need to be passed for each command.

Be sure to create new wallets or use empty wallets as participants in the multisig wallet. If you convert a single signature wallet with funds into a multisig wallet, the funds will be lost.

N/N wallet setup

  1. create_wallet
  2. prepare_multisig
  3. make_multisig

N-1/N wallet setup

  1. create_wallet
  2. prepare_multisig
  3. make_multisig
  4. finalize_multisig

M/N wallet setup

  1. create_wallet
  2. prepare_multisig
  3. make_multisig
  4. exchange_multisig_data (multiple rounds)

M/N Setup Details

Since M/N involves a lot of steps, we’ll show the commands using the JSON-RPC API which allows you to automate the process with a script. If you are performing wallet operations with monero-wallet-rpc, you’ll need to pass the --wallet-dir option on startup.

  1. create_wallet (N times)
  2. prepare_wallet (N times, for each wallet)
  3. make_multisig (N times, for each wallet)
  4. exchange_multisig_data (M-N rounds of N times, for each wallet)
  5. [Optional] is_multisig

1. Create Wallets

First, create N wallets that will participate in the multisig wallet

Request

{
   "jsonrpc": "2.0",
   "id": "0",
   "method": "create_wallet",
   "params": {
       "filename": "wallet_0",
       "password": "",
       "language": "English"
   }
}

Response

{
   "id": "0",
   "jsonrpc": "2.0",
   "result": {}
}

2. Prepare Multisig

Next you will gather the first round of multisig data for each wallet. You need to save the multisig_info return field. Note: if you are fully automating this process using the API, you may also need to make close_wallet and open_wallet calls between each invocation of prepare_multisig. These are left out of this post for brevity.

Request

{
   "jsonrpc": "2.0",
   "id": "0",
   "method": "prepare_multisig"
}

Response

{
   "id": "0",
   "jsonrpc": "2.0",
   "result": {
       "multisig_info": "MultisigV1aFJ22AwxbBW6YkJH9…"
   }
}

3. Make Multisig

The make_multisig command changes each wallet into a multisig wallet. You will need to run it on each wallet participating in the multisig scheme. make_multisig takes two parameters:

  1. multisig_info which is an array of the multisig_info return data from the previous step of all the other wallets except for the wallet being operated on, and
  2. threshold, which is the number of wallets that will need to sign to send a transaction (the “M” in M-of-N).

Like prepare_multisig, make_multisig also returns multisig_info data which needs to be saved and used in subsequent steps

Request

{
   "jsonrpc": "2.0",
   "id": "0",
   "method": "make_multisig",
   "params": {
       "multisig_info": [
           "MultisigV1E1s9eCf4kWDa282j9f…",
           "MultisigV1NahETBVSqVtdbfZ4hz…",
           "MultisigV1SQWPjeNuJKyHT88KA2…",
           "MultisigV1i1UZiz3KtxQSwWReGR…"
       ],
       "threshold": 3
   }
}

Response

{
   "id": "0",
   "jsonrpc": "2.0",
   "result": {
       "address": "41fJjQDhryD11111111111111111111111…...",
       "multisig_info": "MultisigxV1KUADv8n3GBJCrpDu…..."
   }
}

4. Exchange Multisig Keys

The final step to create a multisig wallet is the exchange_multisig_keyscommand. The command takes as parameter multisig_info, which is an array of multisig_info return values from the other wallets in the previous step. The return value also includes another multisig_info field that should be saved for later use.

Depending on your wallet setup, you need to do multiple rounds of exchange_multisig_keys. N-M rounds will be needed for an M/N multisig schema. For example, if you are setting up a 3-of-5 wallet, then 5-3 = 2 rounds will be needed.

In each round, the multisig_info return values from the other wallets in the previous round should be used as parameters. When you reach the last round, the multisig_info return value will be an empty string.

Request

{
   "jsonrpc": "2.0",
   "id": "0",
   "method": "exchange_multisig_keys",
   "params": {
       "multisig_info": [
           "MultisigxV1KUADv8n3GBJCrpDuavNpaPT…",
           "MultisigxV1TJyJjqRwEuPePPE8PuNBLmB…",
           "MultisigxV1jZvNKUnrGsSS85qQiSCs6i3…",
           "MultisigxV16KauRuvCPekZEHdDgjP8Jhf…"
       ]
   }
}

Response

{
   "id": "0",
   "jsonrpc": "2.0",
   "result": {
       "address": "",
       "multisig_info": "MultisigxV1dXxJPiqpUNSU2DjLmX8Ct…"
   }
}

5. (Optional) Check multisig status

At the end of the setup process, you can run the is_multisig command to check that the setup was correct. This returns a JSON object that reports the wallet’s multisig status.

Request

{
   "jsonrpc": "2.0",
   "id": "0",
   "method": "is_multisig"
}

Response

{
   "id": "0",
   "jsonrpc": "2.0",
   "result": {
       "multisig": true,
       "ready": true,
       "threshold": 3,
       "total": 5
   }
}

Spending from your wallets

Hopefully you received good news from the is_multisig command reporting that your wallets are all set up and ready to go. Now it’s time to use them.

Spending from an M/N multisig wallet is the same as spending from other kinds of multisig wallets. So you can follow the process laid out in the guide for N/N and N-1/N.

One trick for using the JSON-API to spend is that you might run into the error LR not found for enough participants. If this happens, the wallets participating in the transaction need to run the refresh command before calling export_multisig_info. If you were using the command line program instead, it would helpfully remind you to run refresh when you need to. Using the JSON-API, you need to know that a refresh is needed to clear this error.

Conclusion

That’s it! You might be intimidated by the the number of steps here, especially if you are trying to coordinate the data exchange between a number of different machines. Thankfully, members of the Monero community are working on software to make the multisig setup process easier. The Monero Messaging System (MMS), which is currently being tested, will provide more guidance and automation in multisig setup and includes secure communication of multisig data across machines.

I hope this guide helps adoption of multisig in Monero.