Skip to content

Multsignature

Learn how to generate, sign, and broadcast transactions using keyring multisig.

Multi-signature account is a Dst account with a special key that requires multiple signatures to sign transactions. This is useful for increasing the security of an account or requiring multiple parties to agree to a transaction. A multi-signature account can be created by specifying:

  • Threshold number of required signatures
  • The public key involved in the signature

To be signed with a multisig account, the transaction must be signed individually by a different key specified for that account. The signatures are then combined into a multisig that can be used to sign transactions. If the number of signatures present is less than the required threshold number, the resulting multisig is considered invalid.

Generate a multi-signature key pair

stcd keys add --multisig=name1,name2,name3[...] --multisig-threshold=K new_key_name

K is the minimum number of private keys that must sign a transaction with a public key address as a signer.

The --multisig flag must contain the names of the public keys that will be combined into a single public key that will be generated and stored in the local database as new_key_name.

All names provided via --multisig must already exist in the local database.

The order in which keys are provided on the command line does not matter unless the flag --nosort is set, i.e. the following command produces two identical keys:

stcd keys add --multisig=p1,p2,p3 --multisig-threshold=2 multisig_address
stcd keys add --multisig=p2,p3,p1 --multisig-threshold=2 multisig_address

Multisig addresses can also be generated on the fly and printed via the which command:

stcd keys show --multisig-threshold=K name1 name2 name3 [...]

Sign transaction

Step 1: Create a multi-signature key

Suppose you have test1 and test2 and want to create a multisignature account using test3.

First import the public key of test3 into your keyring.

stcd keys add \
     test3\
     --pubkey=dstpub1addwnpepqgcxazmq6wgt2j4rdfumsfwla0zfk8e5sws3p3zg5dkm9007hmfysxas0u2

Generate a multi-signature key with a 2/3 threshold.

stcd keys add \
     multi \
     --multisig=test1,test2,test3 \
     --multisig-threshold=2

You can see its address and details:

stcd keys show multi

- name: multi
   type: multi
   address: dst1e0fx0q9meawrcq7fmma9x60gk35lpr4xk3884m
   pubkey: dstpub1ytql0csgqgfzd666axrjzq3mxw59ys6yqcd3ydjvhgs0uzs6kdk5fp4t73gmkl8t6y02yfq7tvfzd666axrjzq3sd69kp5usk492x6nehqjal67ynv0nfqapzrz y3gmdk27la0kjfqfzd666axrjzq6utqt639ka2j3xkncgk65dup06t297ccljmxhvhu3rmk92u3afjuyz9dg9
   mnemonic: ""
   threshold: 0
   pubkeys: []

Let's add 10 DST to the multisig wallet:

stcd tx bank send \
     test1\
     dst1e0fx0q9meawrcq7fmma9x60gk35lpr4xk3884m\
     100000000000000000000dst\
     --chain-id=daodst_7000-1 \
     --gas=auto \
     --fees=1000000dst \
     --broadcast-mode=block

Step 2: Create a multi-signature transaction

We want to send 5 DST from our multisig account to dst1rgjxswhuxhcrhmyxlval0qa70vxwvqn2e0srft.

stcd tx bank send \
     dst1rgjxswhuxhcrhmyxlval0qa70vxwvqn2e0srft\
     dst157g6rn6t6k5rl0dl57zha2wx72t633axqyvvwq \
     50000000000000000000dst \
     --gas=200000 \
     --fees=1000000dst \
     --chain-id=daodst_7000-1 \
     --generate-only > unsignedTx.json

The file unsignedTx.json contains unsigned transactions encoded in JSON.

{
  "body": {
    "messages": [
      {
        "@type": "/cosmos.bank.v1beta1.MsgSend",
        "from_address": "dst1rgjxswhuxhcrhmyxlval0qa70vxwvqn2e0srft",
        "to_address": "dst157g6rn6t6k5rl0dl57zha2wx72t633axqyvvwq",
        "amount": [
          {
            "denom": "dst",
            "amount": "5000000000000000000"
          }
        ]
      }
    ],
    "memo": "",
    "timeout_height": "0",
    "extension_options": [],
    "non_critical_extension_options": []
  },
  "auth_info": {
    "signer_infos": [],
    "fee": {
      "amount": [
        {
          "denom": "dst",
          "amount": "1000000"
        }
      ],
      "gas_limit": "200000",
      "payer": "",
      "granter": ""
    }
  },
  "signatures": []
}

Step 3: Sign alone

Sign with test1 and test2 and create individual signatures.

stcd tx sign \
     unsignedTx.json \
     --multisig=dst1e0fx0q9meawrcq7fmma9x60gk35lpr4xk3884m \
     --from=test1 \
     --output-document=test1sig.json\
     --chain-id=daodst_7000-1
stcd tx sign \
     unsignedTx.json \
     --multisig=dst1e0fx0q9meawrcq7fmma9x60gk35lpr4xk3884m\
     --from=test2 \
     --output-document=test2sig.json\
     --chain-id=daodst_7000-1

Step 4: Create Multisig

Combined with the signature to sign the transaction.

stcd tx multisign \
     unsignedTx.json \
     multi \
     test1sig.json test2sig.json\
     --output-document=signedTx.json\
     --chain-id=daodst_7000-1

TX is now signed:

{
  "body": {
    "messages": [
      {
        "@type": "/cosmos.bank.v1beta1.MsgSend",
        "from_address": "dst1rgjxswhuxhcrhmyxlval0qa70vxwvqn2e0srft",
        "to_address": "dst157g6rn6t6k5rl0dl57zha2wx72t633axqyvvwq",
        "amount": [
          {
            "denom": "dst",
            "amount": "5000000000000000000"
          }
        ]
      }
    ],
    "memo": "",
    "timeout_height": "0",
    "extension_options": [],
    "non_critical_extension_options": []
  },
  "auth_info": {
    "signer_infos": [
      {
        "public_key": {
          "@type": "/cosmos.crypto.multisig.LegacyAminoPubKey",
          "threshold": 2,
          "public_keys": [
            {
              "@type": "/cosmos.crypto.secp256k1.PubKey",
              "key": "ApCzSG8k7Tr4aM6e4OJRExN7cNtvH21L9azbh+uRrvt4"
            },
            {
              "@type": "/cosmos.crypto.secp256k1.PubKey",
              "key": "Ah91erz8ChNanqLe9ea948rvAiXMCRlR5Ka7EE/c0xUK"
            },
            {
              "@type": "/cosmos.crypto.secp256k1.PubKey",
              "key": "A0OjtIUCFJM3AobJ9HJTWKP9RZV2+WPcwVjLgsAidrZ/"
            }
          ]
        },
        "mode_info": {
          "multi": {
            "bitarray": {
              "extra_bits_stored": 3,
              "elems": "wA=="
            },
            "mode_infos": [
              {
                "single": {
                  "mode": "SIGN_MODE_LEGACY_AMINO_JSON"
                }
              },
              {
                "single": {
                  "mode": "SIGN_MODE_LEGACY_AMINO_JSON"
                }
              }
            ]
          }
        },
        "sequence": "1"
      }
    ],
    "fee": {
      "amount": [
        {
          "denom": "dst",
          "amount": "1000000"
        }
      ],
      "gas_limit": "200000",
      "payer": "",
      "granter": ""
    }
  },
  "signatures": [
    "CkCEeIbeGc+I1ipZuhp/0KhVNnWAv2tTlvgo5x61lzk1KHmLPV38m/YFurrFt5cm5+fqIXrn+FlOjrJuzBhw8ogYCkCawm9mpXsBHk0CFsE5618fVnvScEkfrzW0c2jCcjqV8EPuj3ut74UWzZyQkwtJGxUWtro9EgnGsB7Di1Gzizst"
  ]
}

Step 5: broadcast transaction

stcd tx broadcast signedTx.json \
    --chain-id=daodst_7000-1 \
    --broadcast-mode=block