key-manager.md 7.5 KB

key-manager服务

key-manager是一个助记词账户管理服务,包括助记词创建,助记词加密,钱包派生,钱包查询,白名单机制,交易签名等功能。使用grpc作为服务交互协议,方便多语言之间交互。

功能:

  • 设置密码
    • 设置的密码,将作为加密助记词的密码。务必保存好该密码,否则将丢失所有的助记词并且key-manager也将无法启动。(key-manager在启动时会校验密码)
  • 创建多个助记词

    • 创建助记词时需指定 name,name全局唯一,是即将要创建的助记词的代号
  • 助记词加密

    • 创建的助记词将会被加密存储在mysql中,在运行中要注意对mysql的备份
  • 创建eth和tron地址

    • 通过助记词name,network,以及index,可创建对应网络的私钥和地址
  • 白名单机制

    • 服务为交易签名时,将识别资金接收地址,只有接收地址在白名单内,服务才会进行签名,否则将会拒绝签名。
    • 白名单地址列表只有在服务启动时进行加载,不会在运行中热加载,因为防止mysql被攻击。如果想要增加白名单,需在mysql中增加地址后,重启key-manager服务。
  • 为eth和tron交易签名

    • key-manager接收经过编码的交易,反解码为交易详情,检查交易目的地址是否在白名单内,在白名单内时,将进行签名。并将签名过的交易进行编码返回。

Proto文件

根据该proto文件,自动生成客户端请求代码

java生成参考,关键字:grpc生成java代码

https://developer.aliyun.com/article/679610

https://zhuanlan.zhihu.com/p/365370775

syntax = "proto3";
package service;

option java_package = "proto.keyManager";
option java_outer_classname = "keyManagerProto";

option go_package = "../service";

message CreateMnemonicRequest {
    string name = 1; // 商户名字,名字全局唯一,每个商户只能生成一个助记词
    int64 mnemonicType = 2; // 0 or 1, 0代表12个助记词,1代表24个助记词
}

message CreateMnemonicResponse {
  string code = 1;  // 响应码, 成功是200
  string msg = 2;   // 响应描述信息
}

message CreateKeyRequest {
    string name = 1; // 商户名字,如果该商户未创建助记词,则返回错误
    string network = 2; // 链网络名称,"eth" 或 "tron"
    int64 index = 3; // 派生账户使用的index,如果该index已被使用,则返回错误
}

message GetIndexRequest {
    string network = 1; // 链网络名称,"eth" 或 "tron"
    string address = 2; // 查询该地址对应的商户名字和index
}

message GetAddressRequest {
    string name = 1; // 商户名字,如果该商户未创建助记词,则返回错误
    string network = 2; // 链网络名称,"eth" 或 "tron"
    int64 index = 3; // 派生账户使用的index
}

message KeyResponse {
  string code = 1;  // 响应码, 成功是200
  string msg = 2;   // 响应描述信息
  string network = 3; // 链网络名称,"eth" 或 "tron"
  string name = 4; // 商户名字
  int64 index = 5; // 派生账户使用的index
  string address = 6; // 地址
}

message SignRequest {
   string network = 1; // 链网络名称,"eth" 或 "tron"
   string sender = 2; // 签名地址
   string tx = 3; // 编码的交易,先将eth/tron交易Marshal为字符数组,再编码为hex字符串
}

message SignResponse {
  string code = 1;  // 响应码, 成功是200
  string msg = 2;   // 响应描述信息
  string network = 3; // 链网络名称,"eth" 或 "tron"
  string sender = 4; // 签名地址
  string signedTx = 5; // 编码的已签名交易,先将eth/tron已签名交易Marshal为字符数组,再编码为hex字符串
}

service KeyManager {
    rpc CreateMnemonic(CreateMnemonicRequest) returns(CreateMnemonicResponse) {}
    rpc CreateKey(CreateKeyRequest) returns(KeyResponse) {}
    rpc GetIndex(GetIndexRequest) returns(KeyResponse) {}
    rpc GetAddress(GetAddressRequest) returns(KeyResponse) {}
    rpc Sign(SignRequest) returns(SignResponse) {}
}

交易编解码规则

对于Sign服务参数的构造,接收三个参数,分别是:

  • 网络,必须填写 eth或者 tron
  • sender,是交易发送者地址,即签名地址
  • tx,是经过编码的交易
message SignRequest {
   string network = 1; // 链网络名称,"eth" 或 "tron"
   string sender = 2; // 签名地址
   string tx = 3; // 编码的交易,先将eth/tron交易Marshal为字符数组,再编码为hex字符串
}

其中tx的编解码规则如下:

eth

编码规则(请求参数构建):

解码已签名交易(返回参数解析):

  • 先将字符串hex解码为byte数据,再将byte数组json解码为eth交易Transaction

java的以太坊库可参考 https://github.com/web3j/web3j

tron

编码规则(请求参数构建):

解码已签名交易(返回参数解析):

  • 先将字符串hex解码为byte数据,再将byte数组proto解码为tron交易Transaction

tron协议实现就是java,相关交易构建,编解码应该都有

https://github.com/tronprotocol/java-tron

请求参数示例

CreateMnemonic

{"name":"test", "mnemonicType": 0}

CreateKey

{"name":"test4", "network": "eth", "index": 0}

{"name":"test4", "network": "tron", "index": 0}

GetIndex

{"network": "tron", "address": "TQxgjRTVjx6QsK4huSv2Ex3aUDJTs9g6X2"}

{"network": "eth", "address": "0x313A1F70aCA7dE919ff2104F50f94985308E38A8"}

GetAddress

{"name": "test", "network": "tron", "index": 0}

{"name": "test4","network": "eth", "index": 0}

Sign

{"network":"eth","sender":"0x313A1F70aCA7dE919ff2104F50f94985308E38A8","tx":"7b2274797065223a22307832222c226e6f6e6365223a22307830222c226761735072696365223a6e756c6c2c226d61785072696f72697479466565506572476173223a22307832373130222c226d6178466565506572476173223a22307832373130222c22676173223a22307832373130222c2276616c7565223a22307830222c22696e707574223a22307861393035396362623030303030303030303030303030303030303030303030303038656636313166363961623438613331666666373338303038386561613130366133626435613530303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030306634323430222c2276223a22307830222c2272223a22307830222c2273223a22307830222c22746f223a22307861306238363939316336323138623336633164313964346132653965623063653336303665623438222c22636861696e4964223a22307831222c226163636573734c697374223a5b5d2c2268617368223a22307832366136326435343633306436626265313431613038306666663463646264346533346363613932343535386531643063383063643065303830643632316566227d"}

{"network":"tron","sender":"TLZMwPhCvqGt8w4523L7ciMcEG4EWwxWKP","tx":"0ad0010a028042220801a85c6e6c4861f740c8938b95a1315aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a1541dc05f6df15aa25676218932957337f6dadd5fc91121541a614f803b6fd780986a42c78ec9c7f77e6ded13c2244a9059cbb0000000000000000000000008405fb55ed44d8212061672a83ddaafecec3388f00000000000000000000000000000000000000000000000000000000000f424070dbcb8795a131900132"}