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!