多重签名
Sui 支持多重签名(multisig)交易,这需要多个密钥进行授权,而不是单一的、单密钥签名。在技术术语中,Sui 支持 k
对 n
多重签名交易,其中 k
是阈值,n
是所有参与方的总权重。最大参与方数量为 10。要了解 Sui 支持的单密钥签名,详见签名。
多重签名的有效参与密钥是纯 Ed25519、ECDSA Secp256k1 和 ECDSA Secp256r1。每个参与密钥都设置一个 u8 权重,阈值可以设置为 u16。如果序列化的多重签名包含足够数量的有效签名,其权重之和超过阈值,Sui 将视为多重签名有效,并执行交易。
多重签名的应用
Sui 允许你在单个多重签名帐户中混合和匹配密钥方案。例如,你可以选择一个基于单个 Ed25519 助记词的密钥和两个 ECDSA secp256r1 密钥,以创建一个多重签名帐户,始终需要 Ed25519 密钥,但也需要其中一个 ECDSA secp256r1 密钥进行签名。你可以将此结构用于将移动安全区存储的密钥用作双因素身份验证。
目前,iPhone 和高端 Android 设备仅支持 ECDSA secp256r1 安全区存储的密钥。
与阈值签名相比,多重签名帐户通常更灵活、更容易实现和使用,无需复杂的多方计算(MPC)帐户设置仪式和相关软件,也无需依赖阈值密码提供者。此外,除了能够混合和匹配密钥方案和为每个密钥设置不同的权重(这在阈值密码学中较为复杂)之外,多重签名帐户还是“可核实”和“透明”的设计,因为参与方和观察者都可以看到谁签署了每个交易。另一方面,阈值签名提供了隐藏阈值策略的好处,但也导致单个签名负载,使其与单一密钥帐户无法区分。
Sui 中支持的多重签名结构。
示例工作流
以下步骤演示如何创建多重签名交易,然后使用 Sui CLI 将其提交到本地网络。交易可以是对象的转移、包的发布或升级、对 SUI 的支付等。要了解如何设置本地网络,请参见连接到本地网络。
第 1 步:创建密钥
使用以下命令生成每种支持的密钥方案的 Sui 地址和密钥,并将其添加到 sui.keystore
,然后列出这些密钥。
使用 sui client
来创建不同密钥方案的 Sui 地址。
sui client new-address ed25519
sui client new-address secp256k1
sui client new-address secp256r1
第 2 步:将密钥添加到 Sui 密钥库
使用 sui keytool
列出上一步中创建的签名。
sui keytool list
回应类似于以下内容,但显示的是实际的地址、密钥和对等标识符:
╭────────────────────────────────────────────────────────────────────────────────────────────╮
│ ╭─────────────────┬──────────────────────────────────────────────────────────────────────╮ │
│ │ suiAddress │ <SUI-ADDRESS> │ │
│ │ publicBase64Key │ <PUBLIC-KEY> │ │
│ │ keyScheme │ ed25519 │ │
│ │ flag │ 0 │ │
│ │ peerId │ <PEER-ID> │ │
│ ╰─────────────────┴──────────────────────────────────────────────────────────────────────╯ │
│ ╭─────────────────┬──────────────────────────────────────────────────────────────────────╮ │
│ │ suiAddress │ <SUI-ADDRESS> │ │
│ │ publicBase64Key │ <PUBLIC-KEY> │ │
│ │ keyScheme │ secp256k1 │ │
│ │ flag │ 0 │ │
│ │ peerId │ <PEER-ID> │ │
│ ╰─────────────────┴──────────────────────────────────────────────────────────────────────╯ │
│ ╭─────────────────┬──────────────────────────────────────────────────────────────────────╮ │
│ │ suiAddress │ <SUI-ADDRESS> │ │
│ │ publicBase64Key │ <PUBLIC-KEY> │ │
│ │ keyScheme │ secp256r1 │ │
│ │ flag │ 0 │ │
│ │ peerId │ <PEER-ID> │ │
│ ╰─────────────────┴──────────────────────────────────────────────────────────────────────╯ │
╰────────────────────────────────────────────────────────────────────────────────────────────╯
第 3 布:创建多重签名地址
为了创建一个多重签名地址,请输入用于多重签名地址的公钥列表、它们对应的权重列表和阈值(用实际的值替换 <VARIABLES>
)。
sui keytool multi-sig-address --pks <PUBLIC-KEY-ED25519> <PUBLIC-KEY-SECPK1> <PUBLIC-KEY-SECP256R1> --weights 1 2 3 --threshold 3
回应类似于以下内容:
╭─────────────────┬────────────────────────────────────────────────────────────────────────────────────╮
│ multisigAddress │ <MULTISIG-ADDRESS> │
│ multisig │ ╭────────────────────────────────────────────────────────────────────────────────╮ │
│ │ │ ╭─────────────────┬──────────────────────────────────────────────────────────╮ │ │
│ │ │ │ address │ <SUI-ADDRESS> │ │ │
│ │ │ │ publicBase64Key │ <PUBLIC-KEY> │ │ │
│ │ │ │ weight │ 1 │ │ │
│ │ │ ╰─────────────────┴──────────────────────────────────────────────────────────╯ │ │
│ │ │ ╭─────────────────┬──────────────────────────────────────────────────────────╮ │ │
│ │ │ │ address │ <SUI-ADDRESS> │ │ │
│ │ │ │ publicBase64Key │ <PUBLIC-KEY> │ │ │
│ │ │ │ weight │ 2 │ │ │
│ │ │ ╰─────────────────┴──────────────────────────────────────────────────────────╯ │ │
│ │ │ ╭─────────────────┬──────────────────────────────────────────────────────────╮ │ │
│ │ │ │ address │ <SUI-ADDRESS> │ │ │
│ │ │ │ publicBase64Key │ <PUBLIC-KEY> │ │ │
│ │ │ │ weight │ 3 │ │ │
│ │ │ ╰─────────────────┴──────────────────────────────────────────────────────────╯ │ │
│ │ ╰────────────────────────────────────────────────────────────────────────────────╯ │
╰─────────────────┴────────────────────────────────────────────────────────────────────────────────────╯
第4步:向多重签名地址发送对象
此示例使用默认 URL 从本地网络请求 gas,遵循 连接到本地网络 中的指导。如果在跟随进行操作,请确保用前一步中获得的地址替换 <MULTISIG-ADDR>
。
curl --location --request POST 'http://127.0.0.1:9123/gas' --header 'Content-Type: application/json' --data-raw "{ \"FixedAmountRequest\": { \"recipient\": \"<MULTISIG-ADDR>\" } }"
响应类似于以下内容:
{"transferred_gas_objects":[{"amount":200000,"id":"<OBJECT-ID>", ...}]}
步骤5:序列化任何交易
本节演示如何使用属于多签地址的对象,并将要签名的转账序列化。tx_bytes
值可以是任何序列化的交易数据,其中发送者是多签地址。在sui client -h
的支持命令中(publish
、upgrade
、call
、transfer
、transfer-sui
、pay
、pay-all-sui
、pay-sui
、split
、merge-coin
),使用--serialize-unsigned-transaction
标志以输出Base64编码的交易字节。
sui client transfer --to <SUI-ADDRESS> --object-id <OBJECT-ID> --gas-budget <GAS-AMOUNT> --serialize-unsigned-transaction
Raw tx_bytes to execute: <TX_BYTES>
步骤6:使用两个密钥签名交易
使用以下代码示例,使用sui.keystore
中的两个密钥对交易进行签名。只要将其序列化为flag || sig || pk
,你可以使用其他工具完成此操作。
sui keytool sign --address <SUI-ADDRESS> --data <TX_BYTES>
Raw tx_bytes to execute: <TX_BYTES>
Serialized signature (`flag || sig || pk` in Base64): $SIG_1
sui keytool sign --address <SUI-ADDRESS> --data <TX_BYTES>
Raw tx_bytes to execute: <TX_BYTES>
Serialized signature (`flag || sig || pk` in Base64): $SIG_2
步骤7:将单个签名合并为多签名
此示例演示如何将两个签名合并:
sui 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>
你只需要参与签名的签署者的签名,其权重总和>=k
。你必须提供所有公钥及其权重,以及定义多签地址的阈值。
步骤8:使用多签执行交易
使用sui client
来执行使用多签的交易:
sui client execute-signed-tx --tx-bytes <TX_BYTES> --signatures <SERIALIZED-MULTISIG>