Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Sign in
issue
issue
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 23
    • Issues 23
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Activity
  • Graph
  • Create a new issue
  • Commits
  • Issue Boards
Collapse sidebar

新注册的用户请输入邮箱并保存,随后登录邮箱激活账号。后续可直接使用邮箱登录!

  • chainmaker
  • issueissue
  • Issues
  • #771

Closed
Open
Opened Aug 04, 2023 by ghost chen@ghost47chen1 of 3 tasks completed1/3 tasks

sdk-go 支持使用在专门私钥托管kms签名返回结果构建和发送交易

【提议方】选填

组织/单位/公司/个人的名称/昵称

【需求分类】

  • [] chainmaker-go 新特性
  • bugfix
  • 新项目
  • 其他 sdk-go v2.3.1

其他:

【功能/项目名称】

具体的功能名称或者项目名称,方便以后交流。

【开发周期】

人天

【适配版本】

拟适配/合入的chainmaker-go的版本,要求大版本向前兼容

【功能/项目描述】

具体所要实现的功能详细描述(需求说明、设计文档、如何实现、开发周期等)

目前在开发过程中,发现sdk-go支持构建交易支持方法模式:

  1. 直接使用和链建立连接的客户端用户私钥签名发送交易
  2. 使用一对已知本地私钥公钥签名发送交易。

以上2种满足不了我现在开发需求,我的需求是本地构建好交易payload,然后将payload发送给私钥托管服务器签名返回签名结果,然后本地再使用签名结果构建交易。 本需求优点:sdk-go本地不需要知道用户私钥就依赖私钥托管服务器签名交易,保证用户密钥的安全

【考虑过的其他实现方案】

列举其他实现方案,并对比分析。 我在这里理解目前sdk-go方法

  1. 直接使用和链建立连接的客户端用户私钥签名发送交易(sdk-go 目前支持):对应代码如下
func  SafeMintClientSigner(blockchainReq *types.InvokeCommonReq) (status int64, txId string, err error) {
	......
        contractName := "WDF1"
	method := "safeMint"
	address := userEthAddr
	tokenURI := safeMintParams.TokenURI
	dataByte, err := myAbi.Pack(method, address, tokenURI)
	if err != nil {
		logx.Errorf("abi pack invoke contract param error %v", err)
		return -1, "", errors.New("abi pack invoke contract param error")
	}
	dataString := hex.EncodeToString(dataByte)
	kvs := []*common.KeyValuePair{{
		Key:   "data",
		Value: []byte(dataString),
	}}
        resp, err := chainClient.InvokeContract(contractName, method, txId, kvs, -1, false)
	if err != nil {
		logx.Errorf("client invokeContract to blockchain node failed contractName:%v, method:%v, txId:%v, kvs:%v, error:%v", contractName, method, txId, kvs, err)
		return -1, txId, err
	}
}
  1. 使用一对已知本地私钥公钥签名发送交易(sdk-go 目前支持):对应代码如下。
func SafeMintBySigner(blockchainReq *types.InvokeCommonReq) {
	.....
        contractName := "WDF1"
	method := "safeMint"
	address := userEthAddr
	tokenURI := safeMintParams.TokenURI
	dataByte, err := myAbi.Pack(method, address, tokenURI)
	if err != nil {
		logx.Errorf("abi pack err %v", err)
		return -1, "", err
	}
	dataString := hex.EncodeToString(dataByte)
	kvs := []*common.KeyValuePair{{
		Key:   "data",
		Value: []byte(dataString),
	}}

	//
	vkOrg1Client2 := `-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgfDG3+6qOZAxugx6d
egYRXfQ3gRTTmOMnq7NXgNoAqpqgCgYIKoEcz1UBgi2hRANCAAS32zqeAK+tLlHh
eQOqwa0+lN7J9DZXG+tbCcSBXecSUio7Cw6kBlfTCig+1TYQG2H9iD3sa1X7OaMc
zcq5Rtpl
-----END PRIVATE KEY-----`

	org1CrtClient2 := `-----BEGIN CERTIFICATE-----
MIICcDCCAhagAwIBAgIDA1FXMAoGCCqBHM9VAYN1MIGGMQswCQYDVQQGEwJDTjES
MBAGA1UECBMJR3Vhbmd6aG91MRIwEAYDVQQHEwlHdWFuZ3pob3UxGzAZBgNVBAoT
EnhmLW9yZzEueHVuZmVuZy5jbjESMBAGA1UECxMJcm9vdC1jZXJ0MR4wHAYDVQQD
ExVjYS54Zi1vcmcxLnh1bmZlbmcuY24wHhcNMjMwNjI4MDIxMTIzWhcNMjgwNjI2
MDIxMTIzWjCBjTELMAkGA1UEBhMCQ04xEjAQBgNVBAgTCUd1YW5nemhvdTESMBAG
A1UEBxMJR3Vhbmd6aG91MRswGQYDVQQKExJ4Zi1vcmcxLnh1bmZlbmcuY24xDzAN
BgNVBAsTBmNsaWVudDEoMCYGA1UEAxMfY2xpZW50Mi5zaWduLnhmLW9yZzEueHVu
ZmVuZy5jbjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABLfbOp4Ar60uUeF5A6rB
rT6U3sn0Nlcb61sJxIFd5xJSKjsLDqQGV9MKKD7VNhAbYf2IPexrVfs5oxzNyrlG
2mWjajBoMA4GA1UdDwEB/wQEAwIGwDApBgNVHQ4EIgQggwcV9jiAKZWR5SY1goBT
DIzZPYwDmJtzxlLh36e4j+MwKwYDVR0jBCQwIoAgbr4VzktxCf7Xf4Qdx9hU4ab8
PHvn7ictil4ojDMc7yAwCgYIKoEcz1UBg3UDSAAwRQIgKI5q5WY4YOwnw5beiM1p
4tqea76rM8UA1EZV+AUH4JICIQDiJTg6iBae/6+FQ5jM0DJyLELgoc4b/bCsnLwX
AAd1yQ==
-----END CERTIFICATE-----`

	privateKey, err := asym.PrivateKeyFromPEM([]byte(vkOrg1Client2), []byte(""))
	if err != nil {
		logx.Errorf("parse private %v", privateKey)
		return -1, "", err
	}

	cert, err := sdkutils.ParseCert([]byte(org1CrtClient2))
	if err != nil {
		logx.Errorf("parse certPem err %v", cert)
		return -1, "", err
	}

	signer1 := &sdk.CertModeSigner{
		PrivateKey: privateKey,
		Cert:       cert,
		OrgId:      "xf-org1.xunfeng.cn",
	}

        resp, err := chainClient.InvokeContractBySigner(contractName, method, txId, kvs, -1, false, nil, signer)
	if err != nil {
		logx.Errorf("client invokeContract by signer to blockchain node failed contractName:%v, method:%v, txId:%v, kvs:%v, signer:%v, error:%v", contractName, method, txId, kvs, signer, err)
		return -1, txId, err
	}

}
  1. 我的需求是本地构建好交易payload,然后将payload发送给私钥托管服务器签名返回签名结果,然后本地再使用签名结果构建交易(建议新添加方法)
func SafeMintByPrivateTrustServerUserSigner(blockchainReq *types.InvokeCommonReq) (status int64, txId string, err error) {
	......
	method := "safeMint"
	address := userEthAddr
	tokenURI := safeMintParams.TokenURI
	dataByte, err := myAbi.Pack(method, address, tokenURI)
	if err != nil {
		logx.Errorf("abi pack invoke contract param error %v", err)
		return -1, "", errors.New("abi pack invoke contract param error")
	}
	dataString := hex.EncodeToString(dataByte)
	kvs := []*common.KeyValuePair{{
		Key:   "data",
		Value: []byte(dataString),
	}}
	payload := chainClient.CreatePayload("", common.TxType_INVOKE_CONTRACT, contractName, method, kvs, 0, nil)
	encodePayload, err := proto.Marshal(payload)
	if err != nil {
		logx.Errorf("invoke payload proto marshal error %v", err)
		return -1, "", errors.New("invoke payload proto marshal error")
	}
	resp, err := l.svcCtx.PrivateTrustClient.Sign(l.ctx, &rpc.Request{
		Did:             did,
		PayloadWaitSign: encodePayload,
	})
	if err != nil {
		metrics.CallPrivateTrustServerErrCount.Inc("sign")
		logx.Errorf("private trust server sign contract tx payload error %v", err)
		return -1, "", errors.New("private trust server sign contract tx payload error")
	}

	member := &accesscontrol.Member{}
	err = proto.Unmarshal(resp.Member, member)
	if err != nil {
		logx.Errorf("invoke access control Unmarshal member error %v", err)
		return -1, "", errors.New("invoke access control Unmarshal member error")
	}
	signer2 := &blockchain.Signer{
		Signer:    member,
		Signature: resp.Signature,
	}
	status, txIdRes, err := chainClient.InvokeContractByPayloadSigner(payload, -1, false, signer2)
	if err != nil {
		logx.Errorf("InvokeUserContractNoSyncResult error %v", err)
		return status, txIdRes, err
	}
	return status, txIdRes, nil
}

//新添加方法,命名有待优化
func (cc *ChainClient) InvokeContractByPayloadSigner(payload *common.Payload, timeout int64, withSyncResult bool, signer Signer) (*common.TxResponse, error) {
	//
	//cc.logger.Debugf("[SDK] begin InvokeContractBySigner, [contractName:%s]/[method:%s]/[txId:%s]/[params:%+v]",
		contractName, method, txId, kvs)

	 construct payload
	payload := cc.CreatePayload(txId, common. TxType_INVOKE_CONTRACT, contractName, method, kvs, defaultSeq, limit)

	 Construct TX Req & Sign
	req, err := cc.GenerateTxRequestBySigner(payload, nil, signer)
	if err != nil {
		return nil, err
	}

	 send tx req
	resp, err := cc.sendTxRequest(req, timeout)
	if err != nil {
		return resp, fmt. Errorf("send %s failed, %s", payload. TxType.String(), err. Error())
	}

	if resp. Code == common. TxStatusCode_SUCCESS {
		if withSyncResult {
			r, err := cc.getSyncResult(payload. TxId)
			if err != nil {
				return nil, fmt. Errorf("getSyncResult failed, %s", err. Error())
			}
			resp. Code = r.Result.Code
			resp. Message = r.Result.Message
			resp. ContractResult = r.Result.ContractResult
			resp. TxId = payload. TxId
			resp. TxTimestamp = r.TxTimestamp
			resp. TxBlockHeight = r.TxBlockHeight
		}
	}
	return resp, nil
}

type Signer struct {
	Signer accesscontrol. Member
	Signature []byte
}

func(s *signer) Sign(payload *common. Payload) (signature []byte, err error) {
	return s.Signature, nil
}

func(s *Signer) NewMember() (*accesscontrol. Member, error) {
	return s.Signer, nil
}

【预计影响范围】

描述该功能可能的影响范围,方便评估。 若是新项目则可忽略 预计不会产生大影响,SDK-go添加新的方法直接这种签名、构建和发送交易即可。

【系统信息】

拟支持的系统:要求Linux-x86、Linux-arm-86必须支持,其他信创、龙芯、麒麟、统信尽量支持

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: chainmaker/issue#771

Copyright © 2021 ChainMaker Org. All Rights Reserved. 长安链 版权所有。