Skip to main content

Multisig

IOTA supports multi-signature (multisig) transactions, which require multiple keys for authorization rather than a single, one-key signature. In technical terms, IOTA supports k out of n multisig transactions, where k is the threshold and n is the total weights of all participating parties. The maximum number of parties is 10. To learn more about the single key signatures that IOTA supports, see Signatures.

Valid participating keys for multisig are Pure Ed25519, ECDSA Secp256k1, and ECDSA Secp256r1. A (u8) weight is set for each participating keys and the threshold can be set as u16. If the serialized multisig contains enough valid signatures of which the sum of weights passes the threshold, IOTA considers the multisig valid and the transaction executes.

Applications of multisig

IOTA allows you to mix and match key schemes in a single multisig account. For example, you can pick a single Ed25519 mnemonic-based key and two ECDSA secp256r1 keys to create a multisig account that always requires the Ed25519 key, but also one of the ECDSA secp256r1 keys to sign. You could use this structure for mobile secure enclave stored keys as two-factor authentication.

info

Currently, iPhone and high-end Android devices support only ECDSA secp256r1 enclave-stored keys.

Compared to threshold signatures, a multisig account is generally more flexible and straightforward to implement and use, without requiring complex multi-party computation (MPC) account setup ceremonies and related software, and any dependency in threshold crypto providers. Additionally, apart from the ability to mix and match key schemes and setting different weights for each key (which is complex in threshold cryptography), multisig accounts are "accountable" and "transparent" by design because both participating parties and observers can see who signed each transaction. On the other hand, threshold signatures provide the benefits of hiding the threshold policy, but also resulting in a single signature payload, making it indistinguishable from a single-key account.

Supported structures in IOTA multisig Multisig structures supported in IOTA.

Example workflow

The following steps demonstrate how to create a multisig transaction and then submit it against a local network using the IOTA CLI. A transaction can be the transfer of an object, the publish or upgrade of a package, the payment of IOTA, and so on. To learn how to set up a local network, see Connect to a Local Network.

Step 1: Create keys

Use the following command to generate a IOTA address and key for each supported key scheme and add it to the iota.keystore, then list the keys.

Use iota client to create IOTA addresses of different key schemes.

iota client new-address ed25519
iota client new-address secp256k1
iota client new-address secp256r1

Step 2: Add keys to IOTA keystore

Use iota keytool to list the signatures you created in the previous step.

iota keytool list

The response resembles the following, but displays actual addresses, keys, and peer IDs:

╭────────────────────────────────────────────────────────────────────────────────────────────╮
│ ╭─────────────────┬──────────────────────────────────────────────────────────────────────╮ │
│ │ iotaAddress │ <IOTA-ADDRESS> │ │
│ │ publicBase64Key │ <PUBLIC-KEY> │ │
│ │ keyScheme │ ed25519 │ │
│ │ flag │ 0 │ │
│ │ peerId │ <PEER-ID> │ │
│ ╰─────────────────┴──────────────────────────────────────────────────────────────────────╯ │
│ ╭─────────────────┬──────────────────────────────────────────────────────────────────────╮ │
│ │ iotaAddress │ <IOTA-ADDRESS> │ │
│ │ publicBase64Key │ <PUBLIC-KEY> │ │
│ │ keyScheme │ secp256k1 │ │
│ │ flag │ 0 │ │
│ │ peerId │ <PEER-ID> │ │
│ ╰─────────────────┴──────────────────────────────────────────────────────────────────────╯ │
│ ╭─────────────────┬──────────────────────────────────────────────────────────────────────╮ │
│ │ iotaAddress │ <IOTA-ADDRESS> │ │
│ │ publicBase64Key │ <PUBLIC-KEY> │ │
│ │ keyScheme │ secp256r1 │ │
│ │ flag │ 0 │ │
│ │ peerId │ <PEER-ID> │ │
│ ╰─────────────────┴──────────────────────────────────────────────────────────────────────╯ │
╰────────────────────────────────────────────────────────────────────────────────────────────╯

Step 3: Create a multisig address

To create a multisig address, input a list of public keys to use for the multisig address and a list of their corresponding weights and the threshold (replacing <VARIABLES> with actual values).

iota keytool multi-sig-address --pks <PUBLIC-KEY-ED25519> <PUBLIC-KEY-SECPK1> <PUBLIC-KEY-SECP256R1> --weights 1 2 3 --threshold 3

The response resembles the following:

╭─────────────────┬────────────────────────────────────────────────────────────────────────────────────╮
│ multisigAddress │ <MULTISIG-ADDRESS> │
│ multisig │ ╭────────────────────────────────────────────────────────────────────────────────╮ │
│ │ │ ╭─────────────────┬──────────────────────────────────────────────────────────╮ │ │
│ │ │ │ address │ <IOTA-ADDRESS> │ │ │
│ │ │ │ publicBase64Key │ <PUBLIC-KEY> │ │ │
│ │ │ │ weight │ 1 │ │ │
│ │ │ ╰─────────────────┴──────────────────────────────────────────────────────────╯ │ │
│ │ │ ╭─────────────────┬──────────────────────────────────────────────────────────╮ │ │
│ │ │ │ address │ <IOTA-ADDRESS> │ │ │
│ │ │ │ publicBase64Key │ <PUBLIC-KEY> │ │ │
│ │ │ │ weight │ 2 │ │ │
│ │ │ ╰─────────────────┴──────────────────────────────────────────────────────────╯ │ │
│ │ │ ╭─────────────────┬──────────────────────────────────────────────────────────╮ │ │
│ │ │ │ address │ <IOTA-ADDRESS> │ │ │
│ │ │ │ publicBase64Key │ <PUBLIC-KEY> │ │ │
│ │ │ │ weight │ 3 │ │ │
│ │ │ ╰─────────────────┴──────────────────────────────────────────────────────────╯ │ │
│ │ ╰────────────────────────────────────────────────────────────────────────────────╯ │
╰─────────────────┴────────────────────────────────────────────────────────────────────────────────────╯

Step 4: Send objects to a multisig address

This example requests gas from a local network using the default URL following the guidance in Connect to a Local Network. If following along, be sure to replace <MULTISIG-ADDR> with the address you receive in the previous step.

curl --location --request POST 'http://127.0.0.1:9123/gas' --header 'Content-Type: application/json' --data-raw "{ \"FixedAmountRequest\": { \"recipient\": \"<MULTISIG-ADDR>\" } }"

The response resembles the following:

{"transferred_gas_objects":[{"amount":200000,"id":"<OBJECT-ID>", ...}]}

Step 5: Serialize any transaction

This section demonstrates how to use an object that belongs to a multisig address and serialize a transfer to be signed. The tx_bytes value can be any serialized transaction data where the sender is the multisig address. Use the --serialize-unsigned-transaction flag for supported commands in iota client -h (publish, upgrade, call, transfer, transfer-iota, pay, pay-all-iota, pay-iota, split, merge-coin) to output the Base64 encoded transaction bytes.

iota client transfer --to <IOTA-ADDRESS> --object-id <OBJECT-ID> --serialize-unsigned-transaction

Raw tx_bytes to execute: <TX_BYTES>

Step 6: Sign the transaction with two keys

Use the following code sample to sign the transaction with two keys in iota.keystore. You can do this with other tools as long as you serialize it to flag || sig || pk.

iota keytool sign --address <IOTA-ADDRESS> --data <TX_BYTES>

Raw tx_bytes to execute: <TX_BYTES>
Serialized signature (`flag || sig || pk` in Base64): $SIG_1

iota keytool sign --address <IOTA-ADDRESS> --data <TX_BYTES>

Raw tx_bytes to execute: <TX_BYTES>
Serialized signature (`flag || sig || pk` in Base64): $SIG_2

Step 7: Combine individual signatures into a multisig

This sample demonstrates how to combine the two signatures:

iota keytool multi-sig-combine-partial-sig --pks <PUBLIC-KEY-1> <PUBLIC-KEY-2> <PUBLIC-KEY-3> --weights 1 2 3 --threshold 3 --sigs <SIGNATURE-1> <SIGNATURE-2>

multisig address: <MULTISIG-ADDRESS> # Informational
multisig parsed: <HUMAN-READABLE-STRUCT> # Informational
multisig serialized: <SERIALIZED-MULTISIG>

You need only the signatures of the participating signers whose sum of weights >=k. You must provide all public keys and their weights, and the threshold that defined the multisig address.

Step 8: Execute a transaction with multisig

Use iota client to execute a transaction using multisig:

iota client execute-signed-tx --tx-bytes <TX_BYTES> --signatures <SERIALIZED-MULTISIG>

Question 1/2

What is the maximum number of participating parties allowed in IOTA's multisig transactions?