Build
Multi-signature account

Multi-signature account

This document introduces the use of multi-signature accounts, including how to create multi-signature accounts on the chain through Rooch CLI, how to initiate multi-signature transactions, how to sign transactions, and how to broadcast transactions.

Outline

Rooch As the L2 of Bitcoin, Rooch provides multi-signature functions for L1 transactions and L2 transactions. This article first demonstrates the L1 transaction, that is, the multi-signature transaction of Bitcoin's native asset BTC, and then demonstrates the L2 transaction, that is, the multi-signature transaction of Rooch's RGAS.

Prepare account public key

Next, prepare 3 accounts to demonstrate the function of multi-signature accounts.

Create an account through rooch account create, and view the public key of the corresponding account through rooch account list --json.

$ rooch account list --json

{
  "account1": {
    "address": "rooch1hh9p0twq7yze06tys4lp2dzh3k6s4jgrcu68vqnr5ku8cwuaprjq0y8pml",
    "hex_address": "0xbdca17adc0f10597e964857e1534578db50ac903c734760263a5b87c3b9d08e4",
    "bitcoin_address": "tb1pmmx3fk9e2umvshm4r8j6va9xcrmp2s75r96upfxxyhp8mwyfwwssrql720",
    "nostr_public_key": "npub1ttel8sev7svd5zkw3hmte2wanc33x57uct2nkvgn3vp9djyh67wswma74z",
    "public_key": "0x035af3f3c32cf418da0ace8df6bca9dd9e231353dcc2d53b31138b0256c897d79d",    <= Note here!
    "has_session_key": false,
    "active": false
  },
  "account0": {
    "address": "rooch1r2xgp9uyf7elphd39mssdtf8s99wgjm3fywazgfcdf7pzhnx637skura9n",
    "hex_address": "0x1a8c8097844fb3f0ddb12ee106ad27814ae44b71491dd121386a7c115e66d47d",
    "bitcoin_address": "tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg",
    "nostr_public_key": "npub15te2hf6a65zs8jgu83l33mskc99sm98m8vu4rfsjmujjg7y0xc5sf0u9uy",
    "public_key": "0x02a2f2aba75dd50503c91c3c7f18ee16c14b0d94fb3b3951a612df2524788f3629",    <= Note here!
    "has_session_key": false,
    "active": false
  },
  "default": {
    "address": "rooch1qe8s8rkcds2q0xxq9xhjmfq2mxgs4zmjvlle7dmtnrthndzes0uqmhwzzr",
    "hex_address": "0x064f038ed86c140798c029af2da40ad9910a8b7267ff9f376b98d779b45983f8",
    "bitcoin_address": "tb1ph25pk4xm36y3mt6uwclm0fgj8dgdnf5u7xf987qvyv58x987cldsefe2dh",
    "nostr_public_key": "npub192ydmn6ctgucuc47t4x504844e0grrlt4uztlfr9l44g83a2dw0se6k3p8",
    "public_key": "0x022a88ddcf585a398e62be5d4d47d4f5ae5e818febaf04bfa465fd6a83c7aa6b9f",    <= Note here!
    "has_session_key": false,
    "active": true
  }
}

L1 trading demo

This time we will transfer the BTC on the multi-signature address to the address tb1pmmx3fk9e2umvshm4r8j6va9xcrmp2s75r96upfxxyhp8mwyfwwssrql720.

Create multi-signature

rooch account create-multisign -t 2 -p $Pubkey1 -p $Pubkey2 -p $Pubkey3
  • -t or --threshold specifies the threshold number for multi-signature. If you specify a multi-signature account generated by 3 accounts, specifying -t 2 means that any 2 of the 3 accounts need to co-sign the transaction before this multi-signature transaction can be verified.
  • -p or --public-keys specifies the public keys of accounts participating in multi-signature.
$ rooch account create-multisign -t 2 -p 0x022a88ddcf585a398e62be5d4d47d4f5ae5e818febaf04bfa465fd6a83c7aa6b9f -p 0x02a2f2aba75dd50503c91c3c7f18ee16c14b0d94fb3b3951a612df2524788f3629 -p 0x035af3f3c32cf418da0ace8df6bca9dd9e231353dcc2d53b31138b0256c897d79d

MulitsignAddress: rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty
Multisign Bitcoin Address: tb1przxwx6xdyehpnspdr70jaqjm4g62dedcm4gcvf62qu6xjae6e8tq4mpqvn
Threshold: 2
Participants: 3
Participant 0 Address: rooch1qe8s8rkcds2q0xxq9xhjmfq2mxgs4zmjvlle7dmtnrthndzes0uqmhwzzr
Participant 0 Bitcoin Address: tb1ph25pk4xm36y3mt6uwclm0fgj8dgdnf5u7xf987qvyv58x987cldsefe2dh
Participant 0 Public Key: 0x022a88ddcf585a398e62be5d4d47d4f5ae5e818febaf04bfa465fd6a83c7aa6b9f
Participant 1 Address: rooch1r2xgp9uyf7elphd39mssdtf8s99wgjm3fywazgfcdf7pzhnx637skura9n
Participant 1 Bitcoin Address: tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg
Participant 1 Public Key: 0x02a2f2aba75dd50503c91c3c7f18ee16c14b0d94fb3b3951a612df2524788f3629
Participant 2 Address: rooch1hh9p0twq7yze06tys4lp2dzh3k6s4jgrcu68vqnr5ku8cwuaprjq0y8pml
Participant 2 Bitcoin Address: tb1pmmx3fk9e2umvshm4r8j6va9xcrmp2s75r96upfxxyhp8mwyfwwssrql720
Participant 2 Public Key: 0x035af3f3c32cf418da0ace8df6bca9dd9e231353dcc2d53b31138b0256c897d79d

After we claim tBTC from the multi-signature address in Discord, we transfer 100 sats of tBTC to an account with no balance. The target account demonstrated here is tb1pmmx3fk9e2umvshm4r8j6va9xcrmp2s75r96upfxxyhp8mwyfwwssrql720.

# Switch to the target address to be transferred
$ rooch account switch --address tb1pmmx3fk9e2umvshm4r8j6va9xcrmp2s75r96upfxxyhp8mwyfwwssrql720
The active account was successfully switched to `rooch1hh9p0twq7yze06tys4lp2dzh3k6s4jgrcu68vqnr5ku8cwuaprjq0y8pml`
 
# Check the balance of the target address
$ rooch account balance
                                              Coin Type                                                |      Symbol      | Decimals |             Balance     
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                               Bitcoin                                                 |       BTC        |    8     |                 0       

You can see that the balance of the destination address is 0 sats.

Generate multi-signature transactions

rooch bitcoin build-tx --sender $multisign_bitcoin_address -o $to_address:amount_sats
  • --sender specifies the multi-signature account address.
  • -o specifies the transaction output, that is, the transferred Bitcoin address and the number of Bitcoins (in sats), separated by :.
$ rooch bitcoin build-tx --sender tb1przxwx6xdyehpnspdr70jaqjm4g62dedcm4gcvf62qu6xjae6e8tq4mpqvn -o tb1pmmx3fk9e2umvshm4r8j6va9xcrmp2s75r96upfxxyhp8mwyfwwssrql720:100
 
{
  "content": "70736274ff0100890200000001cc96ee0d7eb17ebc2c1087c2c06d81d2596440b61d0abac4db830461779a5fdd0100000000fdffffff026400000000000000225120decd14d8b95736c85f7519e5a674a6c0f61543d41975c0a4c625c27db88973a19082010000000000225120baa81b54db8e891daf5c763fb7a5123b50d9a69cf19253f80c23287314fec7db000000000001012ba086010000000000225120baa81b54db8e891daf5c763fb7a5123b50d9a69cf19253f80c23287314fec7db2206022a88ddcf585a398e62be5d4d47d4f5ae5e818febaf04bfa465fd6a83c7aa6b9f0400000000000000",
  "output_type": "psbt",
  "path": "/tmp/305da9d77a2af176.psbt"
}

At this time, this multi-signature transaction is stored in the file /tmp/305da9d77a2af176.psbt. Next, we will use the account of the multi-signature participant to sign this transaction.

signature transaction

rooch bitcoin sign-tx -s $Pubkey1_address /tmp/xxxxx.psbt
rooch bitcoin sign-tx -s $Pubkey2_address /tmp/xxxxx.psbt
  • -s Specify the address of the multi-signature participant's public key.

The first participant, here is tb1ph25pk4xm36y3mt6uwclm0fgj8dgdnf5u7xf987qvyv58x987cldsefe2dh:

$ rooch bitcoin sign-tx -s tb1ph25pk4xm36y3mt6uwclm0fgj8dgdnf5u7xf987qvyv58x987cldsefe2dh /tmp/305da9d77a2af176.psbt
Transaction details before signing:
  Version: 2
  Lock time: 0
  Inputs:
    Input 0:
      Previous output: dd5f9a77610483dbc4ba0a1db6406459d2816dc0c287102cbc7eb17e0dee96cc:1
      Sequence: 4294967293
      Script pubkey: OP_PUSHNUM_1 OP_PUSHBYTES_32 baa81b54db8e891daf5c763fb7a5123b50d9a69cf19253f80c23287314fec7db
  Outputs:
    Output 0:
      Value: 0.00000100 BTC
      Script pubkey: OP_PUSHNUM_1 OP_PUSHBYTES_32 decd14d8b95736c85f7519e5a674a6c0f61543d41975c0a4c625c27db88973a1
    Output 1:
      Value: 0.00098960 BTC
      Script pubkey: OP_PUSHNUM_1 OP_PUSHBYTES_32 baa81b54db8e891daf5c763fb7a5123b50d9a69cf19253f80c23287314fec7db
 
Do you want to sign this transaction? [yes/no] >
yes
{
  "content": "02000000000101cc96ee0d7eb17ebc2c1087c2c06d81d2596440b61d0abac4db830461779a5fdd0100000000fdffffff026400000000000000225120decd14d8b95736c85f7519e5a674a6c0f61543d41975c0a4c625c27db88973a19082010000000000225120baa81b54db8e891daf5c763fb7a5123b50d9a69cf19253f80c23287314fec7db0140ac2f1e5e911948450ce37e4033b502edf0750ae04078231f13d382d0efdec3ca1368b9bea7f0bb92d3053baa61ead56ed71796886a57721cc2b2c4acd9412ebb00000000",
  "output_type": "tx",
  "path": "/tmp/305da9d77a2af176.tx"
}

The second participant, here is tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg:

$ rooch bitcoin sign-tx -s tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg /tmp/305da9d77a2af176.psbt
Transaction details before signing:
  Version: 2
  Lock time: 0
  Inputs:
    Input 0:
      Previous output: dd5f9a77610483dbc4ba0a1db6406459d2816dc0c287102cbc7eb17e0dee96cc:1
      Sequence: 4294967293
      Script pubkey: OP_PUSHNUM_1 OP_PUSHBYTES_32 baa81b54db8e891daf5c763fb7a5123b50d9a69cf19253f80c23287314fec7db
  Outputs:
    Output 0:
      Value: 0.00000100 BTC
      Script pubkey: OP_PUSHNUM_1 OP_PUSHBYTES_32 decd14d8b95736c85f7519e5a674a6c0f61543d41975c0a4c625c27db88973a1
    Output 1:
      Value: 0.00098960 BTC
      Script pubkey: OP_PUSHNUM_1 OP_PUSHBYTES_32 baa81b54db8e891daf5c763fb7a5123b50d9a69cf19253f80c23287314fec7db
 
Do you want to sign this transaction? [yes/no] >
yes
{
  "content": "02000000000101cc96ee0d7eb17ebc2c1087c2c06d81d2596440b61d0abac4db830461779a5fdd0100000000fdffffff026400000000000000225120decd14d8b95736c85f7519e5a674a6c0f61543d41975c0a4c625c27db88973a19082010000000000225120baa81b54db8e891daf5c763fb7a5123b50d9a69cf19253f80c23287314fec7db0140ed98589b4abc20b02f9cb66492cddc02239b36712d53d3c88ac61ff67ddb0b9b748aeb270d8857a7229b8268bce4de073d328514246619117ff9cf998067bf5e00000000",
  "output_type": "tx",
  "path": "/tmp/305da9d77a2af176.tx"
}

When the multi-signature transaction meets the threshold number, we can broadcast the multi-signature transaction and the transaction will be uploaded to the chain.

Broadcast the tx

rooch bitcoin broadcast-tx /tmp/xxxxx.tx

After the multi-signature participant signs the multi-signature transaction, a .tx file will be generated in the same directory, here is /tmp/305da9d77a2af176.tx. This file stores the content of the multi-signature transaction. We will Once it is broadcast, it will be uploaded to the chain.

[joe@mx ~]$ rooch bitcoin broadcast-tx /tmp/305da9d77a2af176.tx
"59142915d9a1f301dcd26120fe747a18a9e577cb9d357eae76f12a7ad7a95d30"

Next, we check the balance of the target account:

$ rooch account balance
                                              Coin Type                                                |      Symbol      | Decimals |             Balance     
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                               Bitcoin                                                 |       BTC        |    8     |                100      

Currently, our target account already has 100 sats of BTC.

L2 Transaction Demo

This time we transfer the RGAS on the multi-signature address to the address tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg. At this time, there is no coin on this address:

$ rooch account balance --address tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg
 
                                              Coin Type                                                |      Symbol      | Decimals |             Balance     
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                               Bitcoin                                                 |       BTC        |    8     |                 0       

We will demonstrate transferring 5000 RGAS from a multi-signature account to the account above.

Create multi-signature

Note: If it has already been generated above, you can skip this step!

$ rooch account create-multisign -t 2 -p 0x022a88ddcf585a398e62be5d4d47d4f5ae5e818febaf04bfa465fd6a83c7aa6b9f -p 0x02a2f2aba75dd50503c91c3c7f18ee16c14b0d94fb3b3951a612df2524788f3629 -p 0x035af3f3c32cf418da0ace8df6bca9dd9e231353dcc2d53b31138b0256c897d79d
 
MulitsignAddress: rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty
Multisign Bitcoin Address: tb1przxwx6xdyehpnspdr70jaqjm4g62dedcm4gcvf62qu6xjae6e8tq4mpqvn
Threshold: 2
Participants: 3
Participant 0 Address: rooch1qe8s8rkcds2q0xxq9xhjmfq2mxgs4zmjvlle7dmtnrthndzes0uqmhwzzr
Participant 0 Bitcoin Address: tb1ph25pk4xm36y3mt6uwclm0fgj8dgdnf5u7xf987qvyv58x987cldsefe2dh
Participant 0 Public Key: 0x022a88ddcf585a398e62be5d4d47d4f5ae5e818febaf04bfa465fd6a83c7aa6b9f
Participant 1 Address: rooch1r2xgp9uyf7elphd39mssdtf8s99wgjm3fywazgfcdf7pzhnx637skura9n
Participant 1 Bitcoin Address: tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg
Participant 1 Public Key: 0x02a2f2aba75dd50503c91c3c7f18ee16c14b0d94fb3b3951a612df2524788f3629
Participant 2 Address: rooch1hh9p0twq7yze06tys4lp2dzh3k6s4jgrcu68vqnr5ku8cwuaprjq0y8pml
Participant 2 Bitcoin Address: tb1pmmx3fk9e2umvshm4r8j6va9xcrmp2s75r96upfxxyhp8mwyfwwssrql720
Participant 2 Public Key: 0x035af3f3c32cf418da0ace8df6bca9dd9e231353dcc2d53b31138b0256c897d79d

Generate multi-signature transactions

$ rooch tx build --sender tb1przxwx6xdyehpnspdr70jaqjm4g62dedcm4gcvf62qu6xjae6e8tq4mpqvn --function 0x3::transfer::transfer_coin --args address:tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg --args u256:5000 --type-args 0x3::gas_coin::RGas
 
Build transaction succeeded write to file: /tmp/b034cf66a671f0f7.rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty.rtd

The L2 transaction is constructed here, and the content is stored in the file /tmp/b034cf66a671f0f7.rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty.rtd.

Signature transaction

We sign the L2 multi-signature transaction constructed above.

The first participant, here is tb1ph25pk4xm36y3mt6uwclm0fgj8dgdnf5u7xf987qvyv58x987cldsefe2dh:

$ rooch tx sign -s tb1ph25pk4xm36y3mt6uwclm0fgj8dgdnf5u7xf987qvyv58x987cldsefe2dh /tmp/b034cf66a671f0f7.rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty.rtd
 
Transaction data:
 Sender: rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty
 Sequence number: 2
 Chain id: 2
 Max gas amount: 100000000
 Action: MoveAction::FunctionCall( function_id: 0x0000000000000000000000000000000000000000000000000000000000000003::transfer::transfer_coin,  type_args: [Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000003, module: Identifier("gas_coin"), name: Identifier("RGas"), type_params: [] })], args: ["0x1a8c8097844fb3f0ddb12ee106ad27814ae44b71491dd121386a7c115e66d47d", "0x8813000000000000000000000000000000000000000000000000000000000000"])
 Transaction hash: 0xb034…67f8
 
Do you want to sign this transaction? [yes/no] >
yes
Partially signed transaction is written to "/tmp/b034cf66a671f0f7.1.psrt"
You can send the partially signed transaction to other signers, and sign it later with `rooch tx sign /tmp/b034cf66a671f0f7.1.psrt`

When the first participant signs, another file will be generated, located at /tmp/b034cf66a671f0f7.1.psrt, and the subsequent signers must sign this new file.

The second participant, here is tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg:

$ rooch tx sign -s tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg /tmp/b034cf66a671f0f7.1.psrt
 
Partially signed transaction data:
 Sender: rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty
 Sequence number: 2
 Chain id: 2
 Max gas amount: 100000000
 Action: MoveAction::FunctionCall( function_id: 0x0000000000000000000000000000000000000000000000000000000000000003::transfer::transfer_coin,  type_args: [Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000003, module: Identifier("gas_coin"), name: Identifier("RGas"), type_params: [] })], args: ["0x1a8c8097844fb3f0ddb12ee106ad27814ae44b71491dd121386a7c115e66d47d", "0x8813000000000000000000000000000000000000000000000000000000000000"])
 Transaction hash: 0xb034…67f8
 
 Collected signatures: 1/2
Do you want to sign this transaction? [yes/no] >
yes
Signed transaction is written to "/tmp/b034cf66a671f0f7.rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty.srt"
You can submit the transaction with `rooch tx submit /tmp/b034cf66a671f0f7.rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty.srt`

Here you will be prompted how many signatures have been collected and whether to sign the transaction.

After the signature is completed, you will get a completed transaction file /tmp/b034cf66a671f0f7.rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty.srt. The command line will print a prompt to submit the transaction to the Rooch chain.

Submit transaction

Just submit the multi-signature transaction just now to the chain:

$ rooch tx submit /tmp/b034cf66a671f0f7.rooch1vrg7lzdml74mvhnpke9mfrvgn0esnedf3l6sn52t29qs2j5zy35s6qdlty.srt
 
{
  "sequence_info": {
    "tx_order": "55757601",
    "tx_order_signature": "0x01659cbc0c376a49722732f1cf23688d14f824ce39054eb9bd60023cf03a10a2be56558b8312ac2fcd882b1f47275372b11e342e1947f1cebbe92e7355853fc601026c9e5a00643a706d3826424f766bbbb08adada4dc357c1b279ad4662d2fd1e2e",
    "tx_accumulator_root": "0xa88717a0f1717d85f5cadf526eb3d6f3c13e21fbdb66e0ffd3968bf3ed635d43",
    "tx_timestamp": "1728726645361"
  },
  "execution_info": {
    "tx_hash": "0xb034cf66a671f0f74a790933a033303fe59c94c49eb9c0bd01f6cf2d7df367f8",
    "state_root": "0x967b8237c0b106fbf5ec8d2caa0cea3379dcc61294085fc4d6a7d7be2656306c",
    "event_root": "0x709227a91a0227c892255be1c80583253c132b915c4c870c03e9024a0127f830",
    "gas_used": "1021873",
    "status": {
      "type": "executed"    <= Note here!
    }
  },
...

After seeing the successful execution message, it means that our multi-signature transaction has been successfully executed!

Let’s check the account:

$ rooch account balance --address tb1p488sz4vv4rnc267hd0m7st5dufpmtzv4nw70r7exyfwz60s3rhsqca94sg
                                              Coin Type                                                |      Symbol      | Decimals |             Balance     
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
                                               Bitcoin                                                 |       BTC        |    8     |                 0       
                                         0x3::gas_coin::RGas                                           |       RGAS       |    8     |                5000     

Our target account already has the 5000 RGAS we just transferred.

This is the specific process of L2 multi-signature transaction. It is very similar to L1 transaction. During the signing process, you need to pay attention to the command and the file name passed.

Summary

At this point, I believe you are already familiar with the overall process of how Rooch sends multi-signature transactions under the command line!