MPC Node Service API
接口鉴权说明
Safeheron MPC Node Service 使用 JWT(JSON Web Token) 方式鉴权,开发者需要自己创建 JWT 鉴权密钥对,并将公钥配置到 SMN Service,具体的密钥创建和配置方式请参考《SMN Service 部署》。
开发者使用 JWT 生成 token 时,首先准备需要编码的内容为:
token = {
"app": "safeheron-mpc-node-service",
"uri": path,
"nonce": nonce,
"iat": timestamp_secs,
"exp": iat + seconds_jwt_exp,
"hash": sha256(json.dumps(body_json).encode("utf-8")).hexdigest()
}其中每个字段的含义如下:
- app: 值固定为 safeheron-mpc-node-service
- uri :请求的接口路径,比如:/mpc/ecdsa/keys/keygen
- nonce :用于防重放的随机数,推荐使用 UUIDv4
- iat: UNIX 秒级时间戳,颁发 JWT token 的时间,与当前时间相差不能超过 60 秒
- exp:UNIX 秒级时间戳,JWT token 的失效时间,exp 时间最多比当前时间延后 10 分钟。
- hash:HTTP 请求体数据的摘要,计算方法为:将请求体 body 数据序列化为 JSON 格式后进行 UTF-8 编码,使用 sha256 算法对编码后的字节数据进行计算得到 hash 值,最后把 hash 值编码为 16 进展字符串。如果 body 为空,则对空字节进行计算,计算结果固定为
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
对 token 进行编码和签名,其中 private_key 为 JWT 密钥对中的私钥,签名使用 ES256 算法, 示例如下:
token = jwt.encode(token, key=private_key, algorithm="ES256")
在进行接口调用时,需要在 HTTP 请求时增加 Authorization 请求头,如下:
Authorization: Bearer {token}除以下两个接口外,Safeheron MPC Node Service 其他接口均需 JWT 鉴权:
- 健康检查接口:/check
- PerStop 接口:/preStop
全局 API
Node Info
功能概述
查看 MPC Node 的基本配置信息。
接口地址
GET /node/info
请求参数
无
响应参数
| 参数名 | 类型 | 说明 |
| localParty | object | 本地 Party 相关信息 |
| └─id | int | 当前节点 ID |
| └─tpk | string | 16 进制字符串格式的公钥 |
| relayer | object | Relayer 相关配置 |
| └─address | string | Relayer 连接地址 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "localParty": { "id": 1, "tpk": "040ad492d08ba2f34e8bdf44a079694b47374f89c74265700a57888ea2437ee1f4167f98fa232d33daf24440726b03a08476cd1ef697d4b0a6a145dccbea732202" }, "relayer": { "address": "ws://10.110.1.52:9001" } }, "timestamp": "1694976164457", "code": "200" }
Check
功能概述
检查 MPC Node Service 健康状态。状态为健康时 HTTP 响应码为 200,其他状态 HTTP 响应码为 500;该接口不需要 JWT 鉴权。
接口 URL
GET /check
请求参数
无
响应参数
| 参数名 | 类型 | 说明 |
| version | string | MPC Node Service 的版本,如 1.0.0 |
| status | string | ok:状态正常 stopping:停止中,即将下线 unhealthy:其他情况 |
| teeEngine | object | TEE Engine 版本和状态 |
| └─version | string | 版本,如 1.0.0 |
| └─status | string | ok:状态正常 unhealthy:其他情况 |
| license | object | License 信息 |
| └─licenseId | string | License ID |
| └─customerId | string | 客户信息 |
| └─issued | string | 签发时间,YYYY-MM-dd HH:mm:ss,UTC 时间 |
| └─expiry | string | 过期时间,YYYY-MM-dd HH:mm:ss,UTC 时间 |
| └─gracePeriod | int | 过渡期天数,当 License 已经过期的情况下,如果尚在过渡期内,此时系统依然可用,但请及时更新 License,避免影响业务运行 |
| └─status | string | License 的状态,有以下四种: 1. VALID:License 在有效期内,系统正常提供服务 2. GRACE_PERIOD:License 已经过期,尚在宽限期内,系统正常提供服务,需要及时更新 License 3. EXPIRED: License 已经过期,且过渡期已结束,系统功能受限,需更新 License 4. INVALID: 其他未知情况导致的 License 失效,系统功能受限,请联系 Safeheron 协助处理 |
| └─algorithm | object[] | 许可的 MPC 算法,及在算法下许可的 MPC 协议、曲线、门限、和派生路径 |
| └─name | string | 算法名称,例如:ECDSA-CMP、EdDSA-Lin22、Schnorr-Lin22 |
| └─curve | string[] | 在算法下许可的曲线,例如:Secp256k1 |
| └─threshold | string[] | 在算法下许可的门限,例如:2/2、2/3 |
| └─protocol | string[] | 在算法下许可的 MPC 协议,例如:keygen、refresh |
| └─bip44Path | object | 在算法下许可的 BIP44 派生路径 |
| └─type | sting | ANY:许可任意派生路径 SPECIFIED_PATH_ONLY:仅许可指定的派生路径 |
| └─path | string[] | 当 type 为 SPECIFIED_PATH_ONLY 时,指定可使用的派生路径 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "version": "1.2.0", "status": "ok", "teeEngine": { "version": "1.2.0", "status": "ok" }, "license": { "licenseId": "ecb8e000-9833-4d25-8f4f-d681f4467e5d", "customerId": "customer@example.com", "issued": "2024-06-07 00:00:00", "expiry": "2024-07-07 23:59:59", "gracePeriod": "1", "status": "GRACE_PERIOD", "algorithm": [ { "name": "ECDSA-CMP", "curve": [ "Secp256k1" ], "threshold": [ "2/3" ], "protocol": [ "Keygen", "Sign", "Refresh", "Recover" ], "bip44Path": { "type": "ANY", "path": [] } }, { "name": "EdDSA-Lin22", "curve": [ "Ed25519" ], "threshold": [ "2/2", "2/3" ], "protocol": [ "Keygen", "Sign", "Refresh", "Recover" ], "bip44Path": { "type": "ANY", "path": [] } }, { "name": "Schnorr-Lin22", "curve": [ "Secp256k1" ], "threshold": [ "2/2", "2/3", "3/3", "3/5" ], "protocol": [ "Keygen", "Sign", "Refresh", "Recover" ], "bip44Path": { "type": "ANY", "path": [] } } ] } }, "timestamp": "1720406020598", "code": "200" }
PreStop
功能概述
当开发者希望下线或者重启某个 MPC Node Service 实例时,必须等待当前实例中所有正在进行的 MPC 任务结束才可以关闭或者重启进程,所以提供此接口通知实例准备结束工作。收到接口调用后,健康检查接口状态变更为 stopping,同时 HTTP 状态码返回 500。当所有 MPC 任务结束后,返回本次 preStop HTTP 调用的响应。同时,启动 MPC 任务的接口,如创建私钥分片、签名、刷新和恢复接口,调用时返回特定错误码 M201058,并返回对应错误信息:The new request is not allowed since the MPC Node Service is stopping.
为了防止 preStop 被内网恶意调用,每个实例在启动时独立生成一个 token,该 token 用于 preStop 的简单鉴权,保存 token 的位置为 ./preStop/preStopToken.txt,文件内容中包含了 token。开发者通过查看 preStopToken.txt 内容进行调用 preStop。
接口 URL
GET /preStop
请求参数
| 参数名 | 类型 | 说明 |
| token | string | 启动时生成的 token 字符串,存储路径在 ./preStop/preStopToken.txt |
请求示例
curl -X GET http://127.0.0.1:8080/preStop?token=4322a7b0-6fce-439d-9ea8-2657793e595b
响应参数
| 参数名 | 类型 | 说明 |
| stopped | bool | true |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "stopped": true }, "timestamp": "1694679342012", "code": "200" }
算法 API
创建私钥分片
功能概述
MPC Node 接收到启动私钥分片创建指令后,根据 session ID 和远程参与方信息,启动本次 MPC Session,如果 MPC Session 执行成功,则返回 Key ID 和 xPub(扩展公钥),如果计算失败,返回具体的错误信息。
License 说明
需要 License 授权
接口 URL
| 算法 | 接口 URL |
| ECDSA-CMP | POST /mpc/ecdsa/keys/keygen |
| EdDSA-Lin22 | POST /mpc/eddsa/keys/keygen |
| Schnorr-Lin22 | POST /mpc/schnorr/keys/keygen |
请求参数
| 参数名 | 类型 | 必须 | 说明 |
| sessionId | string | 是 | MPC Session ID,唯一标识一个 MPC 任务,所有 Party 在计算同一个任务时, sessionId 必须一致。sessionId 推荐使用 UUIDv4 |
| threshold | int | 是 | 签名门限 t/n 中的 t 值,可用值由 License 决定,1 < threshold <= totalPartyNum。所有 Party 在计算同一个任务时, threshold 必须一致 |
| totalPartyNum | int | 是 | 签名门限 t/n 中的 n 值,可用值由 License 决定,1 < threshold <= totalPartyNum。所有 Party 在计算同一个任务时, totalPartyNum 必须一致 |
| curveName | string | 是 | 签名算法需要的曲线名称,可用值范围由 License 决定 ECDSA 算法支持的曲线为: Secp256k1 EdDSA 算法支持的曲线为:Ed25519 Schnorr 算法支持的曲线为:Secp256k1 |
| remoteParties | array | 是 | 参与本次 MPC 计算任务的其他方, 不包含自己,数量为 totalPartyNum - 1 |
| └─id | int | 是 | 参与方 Party 的 ID |
| └─tpk | string | 是 | 参与方 Party 的 Tenant Public Key (TPK) |
请求示例
{ "sessionId":"ec1bb356-ddad-40a8-a3ca-1111114", "curveName":"Secp256k1", "threshold":2, "totalPartyNum":3, "remoteParties":[ { "id":2, "tpk":"046fda602cba8f37f0f79d5954590bfbb115318cbf9737ba331499cfa9c45aca37d617efaa3550ad6ba022ebed408bc67bdaf2032d9aa2cdcc6035a970c057bddb" }, { "id":3, "tpk":"0419da2303e7998207e50b42a6e8d5213dd2e484cb6d23873099c39fe3b0a6b70c21811645fc2585135e7c921ef32febb4e5a9cbd4f29ac0fceea1ca419f3ea2ff" } ] }
响应参数
| 参数名 | 类型 | 说明 |
| keyId | string | MPC Session 计算成功,每个参与方会返回相同的 Key ID |
| xPub | string | 扩展公钥,每个参与方会返回相同的 xPub |
| signKeyVersion | string | 私钥分片数据和数据结构版本 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "keyId": "53222cc8dbcdba106db0eedab7439aed29ce38f35dd21b20815acc26943b696c", "signKeyVersion": "1.0.0", "xPub": "xpub661MyMwAqRbcGMbf4djbAiBm7aAa8mivvJFAD6EeHKVrD2fztiJ1HJepY3wYQjeVvfPqAkxiQse5t7ujbAXmN5V9b8ajDmppJKokJdErMf7" }, "timestamp": "1694679760215", "code": "200" }
私钥分片签名
功能概述
MPC Node 接收到启动私钥分片签名指令后,根据 sessionID 和远程参与方启动本次 MPC Session,根据 Key ID 获取本地存储的私钥分片执行 MPC 任务;如果 MPC Session 执行成功,则返回对应响应参数,如果计算失败,返回具体的错误信息。
License 说明
需要 License 授权
接口 URL
| 算法 | 接口 URL |
| ECDSA | POST /mpc/ecdsa/keys/sign |
| EdDSA | POST /mpc/eddsa/keys/sign |
| Schnorr | POST /mpc/schnorr/keys/sign |
请求参数
| 参数名 | 类型 | 必须 | 说明 |
| sessionId | string | 是 | MPC Session ID,唯一标识一个 MPC 任务,所有 Party 在计算同一个任务时, sessionId 必须一致。sessionId 推荐使用 UUIDv4 |
| keyId | string | 是 | 需要使用的私钥分片 ID |
| algoType | string | 是 | 仅 Schnorr 算法签名时需要此参数,该参数支持 LEGACY 和 BIP340 两种类型,参数值不区分大小写;LEGACY 适用于 BCH,BIP340 适用于 BTC |
| digests | array | 是 | 需要签名的消息摘要列表 |
| └─path | string | 是 | 签名使用的 BIP44 路径,不可为空,使用的 BIP44 路径需要 License 授权。输入示例:m/44/60/1/0/0。格式为必须 m 开头,/ 分割路径,每段中间必须整数,整数范围为 [0, 2^32),不能带 ',数字部分字段只能包含 5 段 |
| └─digest | string | 是 | 要签名的数据,使用 16 进制字符串表示,不包含 0x。其中 ECDSA 算法要求此参数大小为 32 字节,EdDSA 和 Schnorr 算法要求此参数大于等于 32 字节,小于等于 1M 字节 |
| remoteParties | array | 是 | MPC Session 的参与方信息,不包含自己,数组长度值应为 threshold - 1,其中 threshold 的值为生成 keyId 对应的私钥分片时传入的 threshold 参数 |
| └─id | int | 是 | 参与方 Party 的 ID |
| └─tpk | string | 是 | 参与方 Party 的 Tenant Public Key(TPK) |
请求示例
{ "sessionId": "ec1bb356-ddad-40a8-a3ca-22222224", "keyId": "33580d9d0a10dae3b0adf10b5569b375754f31dec7f9f5ebce959b86e6ef8e10", "remoteParties": [{ "id": 2, "tpk": "044c9fe3b0f482bd063bcd43beff40b225e064651a040706b5080acd6c416244b5d3e1694a5f664e5b780a30f64d9fa41ab89ff85e270a7d227927a1a473e3398c" }], "digests": [{ "path": "m/44/60/0/0/0", "digest": "bfdd2b55543350d641934b3e7c63fe80727fa52127a98c9ed6dca0824e2cb76c" }] }
响应参数
| 参数名 | 类型 | 说明 |
| signatures | array | |
| └─path | string | 签名使用的 BIP44 路径 |
| └─digest | string | 与请求参数对应的 16 进制格式的待签名数据,字母全小写 |
| └─signature | string | 签名结果 16 进制字符串表示 |
| └─recoveryId | int | EVM 公链签名中的 v,值为 0 或者 1。仅当使用 ECDSA 算法及 Secp256k1 曲线签名时,返回该字段 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "signatures": [{ "path": "m/44/60/0/0/0", "digest": "40a264216e755debc1c65742b260a262e25bac2f6f934823b2220b5020b2bfe6", "signature": "3b07800747b2a4ed96966e391ad9db395ba95c18b80dbccf7d93157ff849648d24e65b9d2d5c69e715c6ab2f2114b54a291156109598cd679c48639df84e41cb", "recoveryId": 0 }] }, "timestamp": "1694679840703", "code": "200" }
私钥分片刷新
功能概述
针对 2/3 门限,当 MPC Node 收到刷新指令后,每个参与方得到一个新的私钥分片,同时对应一组新的 KeyId,如果刷新成功,则返回新的 KeyId。如果刷新失败,则返回失败,需要开发者重新触发刷新。新生成的私钥分片和老的私钥分片对应的扩展公钥保持不变(背后对应的私钥保持不变),老的私钥分片依然可用。老的私钥分片需要开发者根据业务场景,选择适当的时机进行删除。
关于刷新和恢复的区别参考:《Keyless 钱包》。
License 说明
需要 License 授权
接口 URL
| 算法 | 接口 URL |
| ECDSA-CMP | POST /mpc/ecdsa/keys/refresh |
| EdDSA-Lin22 | POST /mpc/eddsa/keys/refresh |
| Schnorr-Lin22 | POST /mpc/schnorr/keys/refresh |
请求参数
| 参数名 | 类型 | 必须 | 说明 |
| sessionId | string | 是 | MPC Session ID,唯一标识一个 MPC 任务,所有 Party 在计算同一个任务时, sessionId 必须一致。sessionId 推荐使用 UUIDv4 |
| keyId | string | 是 | 需要刷新的私钥分片 ID |
| remoteParties | array | 是 | MPC Session 的参与方信息,不包含自己。数组长度值应为 totalPartyNum - 1,其中 totalPartyNum 的值为生成 keyId 对应的私钥分片时传入的 totalPartyNum 参数。 |
| └─id | int | 是 | 参与方 Party 的 ID |
| └─tpk | string | 是 | 参与方 Party 的 Tenant Public Key(TPK) |
请求示例
{ "sessionId": "ec1bb356-ddad-40a8-a3ca-22222224", "keyId": "33580d9d0a10dae3b0adf10b5569b375754f31dec7f9f5ebce959b86e6ef8e10", "remoteParties": [{ "id": 2, "tpk": "044c9fe3b0f482bd063bcd43beff40b225e064651a040706b5080acd6c416244b5d3e1694a5f664e5b780a30f64d9fa41ab89ff85e270a7d227927a1a473e3398c" }, { "id": 3, "tpk": "04b398578127089d06deea4004820ff867c50c22972568f6da00c602af26c19e96339d609f90c236b9d97744a62723c1933a94f8935657c6a35f04701642192aaf" } ] }
响应参数
| 参数名 | 类型 | 说明 |
| keyId | string | MPC Session 计算成功,每个参与方会返回相同的新 KeyId |
| xPub | string | 扩展公钥,和原来一组私钥分片的扩展公钥保持不变 |
| signKeyVersion | string | 私钥分片数据和数据结构版本 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "keyId": "53222cc8dbcdba106db0eedab7439aed29ce38f35dd21b20815acc26943b696c", "signKeyVersion": "1.0.0", "xPub": "xpub661MyMwAqRbcGMbf4djbAiBm7aAa8mivvJFAD6EeHKVrD2fztiJ1HJepY3wYQjeVvfPqAkxiQse5t7ujbAXmN5V9b8ajDmppJKokJdErMf7" }, "timestamp": "1694679840703", "code": "200" }
私钥分片恢复
功能概述
针对 2/3 门限,使用其中两个私钥分片恢复另外一个私钥分片。所有的参与方都必须输入 KeyId,即使本地私钥分片不存在的的参与方,也需要输入 KeyId。RecoveredParty 用于表示需要恢复私钥分片的一方。如果恢复成功,则返回新的 KeyId。如果恢复失败,则返回失败,需要开发者重新触发恢复。新生成的私钥分片和老的私钥分片对应的扩展公钥保持不变(背后对应的私钥保持不变),老的私钥分片依然可用。老的私钥分片需要开发者根据业务场景,选择适当的时机进行删除或者始终保留用于将来的恢复场景。
更多关于恢复私钥分片和私钥分片合成单私钥参考:《Keyless 钱包》。
License 说明
需要 License 授权
接口 URL
| 算法 | 接口 URL |
| ECDSA-CMP | POST /mpc/ecdsa/keys/recover |
| EdDSA-Lin22 | POST /mpc/eddsa/keys/recover |
| Schnorr-Lin22 | POST /mpc/schnorr/keys/recover |
请求参数
| 参数名 | 类型 | 必须 | 说明 |
| sessionId | string | 是 | MPC Session ID,唯一标识一个 MPC 任务,所有 Party 在计算同一个任务时, sessionId 必须一致。sessionId 推荐使用 UUIDv4 |
| keyId | string | 是 | 指定需要使用的私钥分片 ID |
| remoteParties | array | 是 | 所有其他的 MPC Session 参与方信息,不包含自己,数组长度值应为 totalPartyNum - 1,其中 totalPartyNum 的值为生成 keyId 对应的私钥分片时传入的 totalPartyNum 参数 |
| └─id | int | 是 | 参与方 Party 的 ID |
| └─tpk | string | 是 | 参与方 Party 的 Tenant Public Key(TPK) |
| recoveredParty | object | 是 | 需要恢复的一方的 Party 信息 |
| └─id | int | 是 | 被恢复方 Party 的 ID |
| └─tpk | string | 是 | 被恢复方 Tenant Public Key(TPK) |
请求示例
{ "sessionId": "ec1bb356-ddad-40a8-a3ca-22222224", "keyId": "33580d9d0a10dae3b0adf10b5569b375754f31dec7f9f5ebce959b86e6ef8e10", "remoteParties": [{ "id": 2, "tpk": "044c9fe3b0f482bd063bcd43beff40b225e064651a040706b5080acd6c416244b5d3e1694a5f664e5b780a30f64d9fa41ab89ff85e270a7d227927a1a473e3398c" }, { "id": 3, "tpk": "0419da2303e7998207e50b42a6e8d5213dd2e484cb6d23873099c39fe3b0a6b70c21811645fc2585135e7c921ef32febb4e5a9cbd4f29ac0fceea1ca419f3ea2ff" }], "recoveredParty": { "id": 3, "tpk": "0419da2303e7998207e50b42a6e8d5213dd2e484cb6d23873099c39fe3b0a6b70c21811645fc2585135e7c921ef32febb4e5a9cbd4f29ac0fceea1ca419f3ea2ff" } }
响应参数
| 参数名 | 类型 | 说明 |
| keyId | string | recover 后生成新的一组私钥分片的 keyId |
| xPub | string | 扩展公钥,和原来一组私钥分片的扩展公钥保持不变 |
| signKeyVersion | string | 私钥分片数据和数据结构版本 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "keyId":"53222cc8dbcdba106db0eedab7439aed29ce38f35dd21b20815acc26943b696c", "signKeyVersion":"1.0.0", "xPub":"xpub661MyMwAqRbcGMbf4djbAiBm7aAa8mivvJFAD6EeHKVrD2fztiJ1HJepY3wYQjeVvfPqAkxiQse5t7ujbAXmN5V9b8ajDmppJKokJdErMf7" }, "timestamp": "1694679840703", "code": "200" }
根据 KeyId 和 BIP44 路径获取公钥
功能概述
扩展公钥派生子公钥功能。
License 说明
需要 License 授权
接口 URL
| 算法 | 接口 URL |
| ECDSA-CMP | POST /mpc/ecdsa/keys/derivePublicKeys |
| EdDSA-Lin22 | POST /mpc/eddsa/keys/derivePublicKeys |
| Schnorr-Lin22 | POST /mpc/schnorr/keys/derivePublicKeys |
请求参数
| 参数名 | 类型 | 必须 | 说明 |
| keyId | string | 是 | 指定需要使用的私钥分片 |
| compressed | bool | 是 | 是否返回压缩公钥,true 是,返回压缩公钥,false 返回未压缩公钥。仅当 keyId 所对应的算法是 ECDSA 或 Schnorr 时,需要此参数 |
| paths | array | 是 | BIP 44 路径数组,使用的 BIP44 路径需要 License 授权 |
请求示例
{ "keyId": "33580d9d0a10dae3b0adf10b5569b375754f31dec7f9f5ebce959b86e6ef8e10", "compressed": false, "paths": [ "m/44/60/0/0/0", "m/44/666/0/0/0" ] }
响应参数
| 参数名 | 类型 | 说明 |
| paths | array | |
| └─path | string | BIP44 路径 |
| └─pk | string | BIP44 路径对应的公钥 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "paths": [{ "path": "m/44/60/0/0/0", "pk": "049c3e008cb69f759c8657a774f0b7a501e711aa275c8f4e0455a2ef578edb5f65bb9618012449cca190890d28bcb9bb1e9f8b9aabe2c64b6618d7b74774454eba" }] }, "timestamp": "1694679840703", "code": "200" }
验证签名的有效性
功能概述
给定公钥、消息、签名,验证签名是否是一个有效的签名。
接口 URL
| 算法 | 接口 URL |
| ECDSA-CMP | POST /mpc/ecdsa/keys/verifysignature |
| EdDSA-Lin22 | POST /mpc/eddsa/keys/verifysignature |
| Schnorr-Lin22 | POST /mpc/schnorr/keys/verifysignature |
请求参数
| 参数名 | 类型 | 必须 | 说明 |
| curveName | string | 是 | 签名时所使用的曲线,需要与签名时所使用的曲线保持一致 |
| algoType | string | 是 | 仅当要验证的签名是采用 Schnorr 算法生成时需要此参数,需要与签名时所使用的 algoType 参数值保持一致 |
| publicKey | string | 是 | 公钥 |
| digest | string | 是 | 开发者对消息 hash 后的摘要,16 进制字符串 |
| signature | string | 是 | 签名内容,签名接口返回的 16 进制字符串 |
请求示例
{ "curveName": "Secp256k1", "publicKey": "04629a4bba2c960f59cd2356d35038ecc375e8d37bdbf78262bc93cf07cf81999d1d02573386999ebfbea91533d67aabdbc769b9460272cc617c5c94da99456841", "digest": "19f9c9bc1fb14d9286222f22e7191364fe92fbde18be4cb5bd93509adb7451c9", "signature": "eca2298a210d45aa4b13c90862e007f307c365d2d150357332947d9e978742250ab809fc31ca158b8bc1616eb6aca33ed9844e19e252378456f3515bda0dafc8" }
响应参数
| 参数名 | 类型 | 说明 |
| verified | bool | true 表示签名有效,false 签名无效 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "verified": true }, "timestamp": "1694679840703", "code": "200" }
获取私钥分片信息
功能概述
给定私钥分片 KeyId,获取私钥分片的可公开部分信息。
接口 URL
| 算法 | 接口 URL |
| ECDSA-CMP | POST /mpc/ecdsa/keys/info |
| EdDSA-Lin22 | POST /mpc/eddsa/keys/info |
| Schnorr-Lin22 | POST /mpc/schnorr/keys/info |
请求参数
| 参数名 | 类型 | 必须 | 说明 |
| keyId | string | 是 | 私钥分片 ID |
请求示例
{ "keyId": "33580d9d0a10dae3b0adf10b5569b375754f31dec7f9f5ebce959b86e6ef8e10" }
响应参数
| 参数名 | 类型 | 说明 |
| keyId | string | 私钥分片 ID |
| xPub | string | 扩展公钥 |
| curveName | string | 签名算法需要的曲线名称 |
| signKeyVersion | string | 私钥分片数据和数据结构版本 |
| threshold | int | 门限值 |
| totalPartyNum | int | 参与方总数 |
| parentKeyId | string | 如果私钥分片由刷新或者恢复得到,这里为父私钥分片的 keyId,如果为分布式私钥分片生成得到,这里为空 |
| parentType | string | 如果存在 parentKeyId,那么这里为 refresh/recover,如果不存在 parentKeyId,这里为空 |
| createdTimestamp | string | 私钥分片创建时间的毫秒级时间戳 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "keyId": "33580d9d0a10dae3b0adf10b5569b375754f31dec7f9f5ebce959b86e6ef8e10", "curveName": "Secp256k1", "signKeyVersion": "1.0.0", "threshold":2, "totalPartyNum":3, "xPub": "xpub661MyMwAqRbcFLeWpiZraGrGMWPik6eQKkBcck88jmA2WjMZXngZbvsnRxue7b3GEKAP5nNX1kBRWWzFceMEdhixH9ojyK8CNovBjeqmkzV", "parentKeyId": "e28596301d732307402f7cda2220dfd4644116500179aeed53b9808dd0629c93", "parentType": "refresh", "createdTimestamp": "1686184384797", }, "timestamp": "1694679342012", "code": "200" }
从签名中恢复公钥
功能概述
给定摘要、签名和 recoveryId,恢复公钥。仅 ECDAS-CMP 算法支持此接口。
接口 URL
| 算法 | 接口 URL |
| ECDSA-CMP | POST /mpc/ecdsa/keys/recoverPublicKey |
请求参数
| 参数名 | 类型 | 说明 |
| curveName | string | 签名时所使用的曲线,需要与签名时所使用的曲线保持一致 |
| digest | string | 开发者对消息 hash 后的摘要,16 进制字符串 |
| signature | string | 消息摘要对应的签名 |
| recoveryId | int | ECDSA 签名返回的 recoveryId,0 或者 1 |
| compressed | bool | 是否返回压缩公钥,true 返回压缩公钥,false 返回未压缩公钥 |
请求示例
{ "recoveryId":0, "curveName":"Secp256k1", "compressed":false, "digest":"40a264216e755debc1c65742b260a262e25bac2f6f934823b2220b5020b2bfe6", "signature":"7fe87acad1e2c5c482fef578e88130c8cc8acec65b6be046d3ea1593cd1170f729d1b697022504b90106ae40b43e1dd59cca4b2d59aeaccdc076137bfdb62e72" }
响应参数
| 参数名 | 类型 | 说明 |
| publicKey | string | 恢复出来的公钥 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "publicKey": "048993a2f1ad400a243ccbdf0a3193aa766d3ccbe11509c2e18d7c1ea11b942aa22806523c572c5ebd05cac59b27adc169b6ccdcf12a508e0adc952ee970cedd93" }, "timestamp": "1694679342012", "code": "200" }
分页查询 keyId 列表
功能概述
分页查询 keyId 列表,按照创建时间降序查询。
接口 URL
| 算法 | 接口 URL |
| ECDSA-CMP | POST /mpc/ecdsa/keys/list |
| EdDSA-Lin22 | POST /mpc/eddsa/keys/list |
| Schnorr-Lin22 | POST /mpc/schnorr/keys/list |
请求参数
| 参数名 | 类型 | 必须 | 说明 |
| page | int | 是 | 页码 |
| pageSize | int | 是 | 每页数据大小,最大为 200,超过 200 后默认按照 200 进行限制 |
请求示例
{ "page": 1, "pageSize": 20, }
响应参数
| 参数名 | 类型 | 说明 |
| keyIds | array | |
| └─keyId | string | 私钥分片 ID |
| └─curveName | string | 曲线名称 |
| └─xPub | string | 扩展公钥 |
| └─signKeyVersion | string | 私钥分片数据和数据结构版本 |
| └─threshold | int | 签名门限 |
| └─totalPartyNum | int | MPC 参与方总个数 |
| └─parentKeyId | string | 如果私钥分片由刷新或者恢复得到,这里为父私钥分片的 keyId,如果 keygen 得到,这里为空 |
| └─parentType | string | 如果存在 parentKeyId,那么这里为 refresh/recover,如果不存在 parentKeyId,这里为空 |
| └─createdTimestamp | string | 创建时间,采用毫秒时间戳 |
| currentPage | int | 当前页码 |
| totalPage | int | 总页数 |
| pageSize | int | 当前页数据大小 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "currentPage": 1, "totalPage": 1, "pageSize": 20, "keyIds": [{ "keyId": "4be9109c57b3b6edda7395d5ff65f6565710bece37bc9847e86938bd7c1a242f", "curveName": "Secp256k1", "xPub": "xpub661MyMwAqRbcGYn3pcY5KUz7y8SGZ7zEZrnroPYDnx8wTw2Hrvc16kHEMagSkjrV9rMJ1fEu1A1KLSDsu5tEPCQEhtnYqHnFHfPBE5Wsgbq", "parentKeyId": "", "parentType": "", "signKeyVersion": "1.4.0", "createdTimestamp": "1697538104000" }] }, "timestamp": "1694679342012", "code": "200" }
删除私钥分片
功能概述
指定 keyId,物理删除指定的私钥分片,一旦删除不可恢复。
接口 URL
| 算法 | 接口 URL |
| ECDSA-CMP | POST /mpc/ecdsa/keys/delete |
| EdDSA-Lin22 | POST /mpc/eddsa/keys/delete |
| Schnorr-Lin22 | POST /mpc/schnorr/keys/delete |
| 参数名 | 类型 | 必须 | 说明 |
| keyId | string | 是 | 私钥分片的 keyId |
请求示例
{ "keyId": "33580d9d0a10dae3b0adf10b5569b375754f31dec7f9f5ebce959b86e6ef8e10" }
响应参数
| 参数名 | 类型 | 说明 |
| deleted | bool | true 表示删除成功,false 表示删除失败 |
响应示例
{ "success": true, "errCode": null, "errMsg": null, "data": { "deleted": true }, "timestamp": "1694679342012", "code": "200" }
错误码
| 错误码 | 说明 |
| M201001 | Ready message algoId mismatch 和其他 MPC 参与方发送的 Ready 消息中 algoId 对比不一致 |
| M201002 | Ready message curveId mismatch 和其他 MPC 参与方发送的 Ready 消息中 curveId 对比不一致 |
| M201003 | Ready message algoVersion mismatch 和其他 MPC 参与方发送的 Ready 消息中 algoVersion 对比不一致 |
| M201004 | Ready message keyId mismatch 和其他 MPC 参与方发送的 Ready消息中 keyId 对比不一致 |
| M201005 | Ready message sessionId mismatch 和其他 MPC 参与方发送的 Ready消息中 sessionId 对比不一致 |
| M201006 | Ready message taskHash mismatch 和其他 MPC 参与方发送的 Ready 消息待签内容的摘要对比不一致 |
| M201007 | Ready remote party error Ready 消息来源和入参 remoteParties 对比不一致 |
| M201008 | Ready timeout 等他其他参与方 Ready 消息超时,超过配置文件中 ReadyTimeout 配置 |
| M201009 | Ready message send error 发送 Ready 消息失败 |
| M201010 | Ready message chainCode mismatch 和其他 MPC 参与方发送的 Ready 消息中 chainCode 对比不一致 |
| M201011 | Ready message rcKeyId mismatch 和其他 MPC 参与方发送的 Ready 消息中 rcKeyId 对比不一致 |
| M201012 | Ready message verify exception Ready 消息校验异常 |
| M201013 | Ready message signKeyVersion mismatch 和其他 MPC 参与方发送的 Ready 消息中 signKeyVersion 兼容性检查异常 |
| M201014 | Ready message algoType mismatch 和其他 MPC 参与方发送的 Ready 消息中 algoType对比不一致 |
| M201021 | MPC session timeout MPC 计算超时失败,超过配置文件中的 SessionTimeout 配置 |
| M201022 | MPC engine run context error MPC 创建计算上下文 context 失败 |
| M201023 | MPC engine run mid round error MPC 执行 midRound 失败 |
| M201024 | MPC engine run final round error MPC 执行 finalRound 失败 |
| M201025 | MPC engine create key error 创建鉴权公私钥失败 |
| M201026 | MPC websocket communicate error WebSocket 通信失败 |
| M201027 | MPC create session error 创建 MPC Session 失败 |
| M201028 | Duplicate calls sessionId error 重复的 sessionId 错误 |
| M201029 | Mpc engine offline error MPC Engline 工作状态异常 |
| M201030 | Mpc engine recover userKeyShare error MPC Engine 恢复 userKeyShare 失败 |
| M201031 | MPC engine timeout error MPC 计算超时错误 |
| M201032 | MPC engine recover minimal key error MPC 恢复计算过程中 minimalKey 失败 |
| M201033 | MPC engine input chianCode empty error MPC 检查 chainCode 字段出现错误 |
| M201034 | Prestop token is invalid preStop token 不合法 |
| M201051 | The input parameter is empty error 输入参数为空失败 |
| M201052 | The input parameter is invalid error 输入参数超出范围 |
| M201053 | The signkey is empty error SMN Service 存储的 signKey 为空 |
| M201054 | The bip44 path is illegal error BIP44 路径非法 |
| M201055 | The input parameter %s is invalid hex format error 16 进制格式校验错误 |
| M201056 | The input parameter conflict with config error 输入参数和配置参数冲突 |
| M201057 | Check failed, entering preStop status check 接口自检异常,进入preStop 状态 |
| M201058 | The new request is not allowed since the MPC Node Service is stopping 新请求不再响应,因为服务被调用过 preStop 接口正在停止中 |
| M201059 | The format of sessionId does not conform to the specified format. sessionId 格式不符合规则 |
| M201060 | The keyId %s doesn’t exist. keyId 不存在 |
| M201062 | The given remote party %s cannot be the same as the local party. 传入的 remoteParty 不能和本地party相同 |
| M201063 | The two given remote party IDs cannot be the same. 传入的 2 个 remoteParty ID 不能相同 |
| M201064 | The given remote party ID must be in the range of [1,2,3]. 传入的 remoteParty ID 必须在 [1,2,3] 范围内 |
| M201065 | The given remote tpk is not in the correct format 传入的 remoteParty tpk 格式不正确 |
| M201066 | The given remote parties count is not correct of threshold. 传入的 remoteParties 数量和 threshold 不匹配 |
| M201067 | The given recovered tpk is not in the correct format. 传入的 recovered tpk 格式不正确 |
| M201068 | The given recovered party %s should not in the remoteParties. 被恢复方调用接口时,传入的 remoteParties 不应该包含自己 |
| M201069 | The given recovered party %s should in the remoteParties. 被恢复方信息在 remoteParties 也应该包含 |
| M201070 | The given recovered party ID must be in the range of [1,2,3]. 传入的 recoveredParty ID 必须在 [1,2,3] 范围内 |
| M201071 | sessionId=%s. The path cannot be empty path 不能为空 |
| M201072 | sessionId=%s. The digest should be 64 chars in length digest 应该是64字符长度 |
| M201073 | sessionId=%s. The threshold cannot be empty threshold 不能为空 |
| M201074 | sessionId=%s. The totalPartyNum cannot be empty totalPartyNum 不能为空 |
| M201075 | sessionId=%s. The sessionId should be between 32 and 64 chars in length sessionId 应该在32到64字符长度之间 |
| M201076 | sessionId=%s. The curveName should be below 64 chars length curveName 应该小于64字符长度 |
| M201077 | sessionId=%s. The remoteParties cannot be empty remoteParties 不能为空 |
| M201078 | sessionId=%s. The keyId should be 64 chars in length keyId 应该是64字符长度 |
| M201079 | sessionId=%s. The page should be greater than 0 page 应该大于0 |
| M201080 | sessionId=%s. The page should be less than 99999999 page 应该小于99999999 |
| M201081 | sessionId=%s. The pageSize should be greater than 0 pageSize 应该大于0 |
| M201082 | sessionId=%s. The id cannot be empty id 不能为空 |
| M201083 | sessionId=%s. The recoveredParty cannot be null recoveredParty 不能为空 |
| M201084 | sessionId=%s. The signature should be 128 chars in length signature应该是128字符长度 |
| M201085 | sessionId=%s. The recoveryId should be 0 or 1 recoveryId 应该是0或1 |
| M201086 | sessionId=%s. The digests cannot be empty digests 不能为空 |
| M201087 | sessionId=%s. The publicKey should be 130 chars in length publicKey 应该是130字符长度 |
| M201088 | sessionId=%s. The compressed cannot be empty compressed 不能为空 |
| M201089 | sessionId=%s. The paths cannot be empty paths 不能为空 |
| M201090 | sessionId=%s. The page cannot be empty page 不能为空 |
| M201091 | sessionId=%s. The pageSize cannot be empty pageSize 不能为空 |
| M201092 | sessionId=%s. The recoveryId cannot be empty recoveryId 不能为空 |
| M201093 | sessionId=%s. The publicKey %s invalid format error publicKey 格式错误 |
| M201094 | sessionId=%s. The digest length should be between 64 and 2097152 chars in length digest 长度应该在64到2097152字符之间 |
| M201095 | Input curveName invalid error 参数 curveName 不支持 |
| M201096 | Input algoType invalid error 参数 algoType 不支持 |
| M201999 | Unknown exception error 未知异常失败 |
文档变更记录
2024-07-04 1.2.0 版本更新
- check 接口增加 License 数据返回
- 相关接口及参数增加 License 授权说明
- 分页查询 keyId 列表接口新增返回 threshold 和 totalPartyNum 两个数据