如何从UI获取数字签名并用于Corda R3区块链交易验证
Corda多节点交易签名校验完整实现流程
前置实现:多参与方节点创建与约束配置
- 节点配置:在
build.gradle的node闭包下定义多个参与方节点,分别配置符合X500格式的name、p2pPort、rpcPort、rpcSettings等参数,每个节点对应独立的身份密钥对,部署后自动生成节点证书与密钥库 - 交易约束配置:在CorDapp的状态定义中添加约束,常用
SignatureAttachmentConstraint(要求合约Jar由指定密钥签名)或者HashAttachmentConstraint(要求合约Jar哈希匹配固定值),同时在状态的participants字段中明确所有需要参与签名的节点身份。
问题1:从UI端获取数字签名
- 先为Corda节点的RPC用户分配
SignTransactionFlow的启动权限,开放签名调用能力 - UI端通过封装好的REST接口或者原生RPC客户端,向对应参与方节点提交待签名的交易ID(或序列化后的交易字节流)
- 节点收到请求后先校验当前登录用户是否为该节点签名密钥的授权持有人,校验通过后返回交易详情供UI展示,用户在UI完成确认操作后,触发节点内部的签名逻辑
- 节点生成的签名以字节数组形式返回,可序列化为Base64字符串供UI端传输、存储
注意:禁止在UI端直接持有节点私钥,所有签名运算必须在Corda节点内部完成,UI仅做身份校验和确认触发入口
问题2:完成交易签名操作
完整的交易签名流程如下:
- 发起方节点构建交易:调用
TransactionBuilder传入公证人身份,依次添加交易输入状态、输出状态、合约指令 - 发起方自签名:调用
signInitialTransaction方法用发起方私钥完成首次签名,得到部分签名交易(SignedTransaction,简称STX) - 跨节点收集签名:将部分签名的STX通过
SendTransactionFlow发送给其他需要签名的参与方节点,对方节点收到后运行SignTransactionFlow,校验交易符合业务规则后返回对应签名 - 合并签名并提交公证:所有签名收集完成后调用
addSignature方法将所有参与方签名合并到STX中,得到完整签名的交易,再提交给公证人做双花校验,公证人签名后交易正式生效。
参考代码示例:
// 1. 构建交易 val txBuilder = TransactionBuilder(notary = notaryParty) .addInputState(inputStateRef) .addOutputState(tradeOutputState) .addCommand(TradeContract.Commands.Transfer(), listOf(partyA.owningKey, partyB.owningKey)) // 2. 发起方自签名 val selfSignedTx = serviceHub.signInitialTransaction(txBuilder) // 3. 收集对手方签名 val otherPartySession = initiateFlow(partyB) val fullySignedTx = subFlow(CollectSignaturesFlow(selfSignedTx, listOf(otherPartySession))) // 4. 提交公证完成交易 val finalizedTx = subFlow(FinalityFlow(fullySignedTx, listOf(otherPartySession)))
问题3:其他节点完成交易校验
- 交易通过公证人校验后,会通过
FinalityFlow广播到所有交易涉及的参与方节点 - 接收方节点收到交易后自动运行
ReceiveFinalityFlow,默认执行三层校验:- 签名校验:校验交易上所有必填参与方的签名是否合法、是否匹配对应公钥,公证人签名是否有效
- 合约校验:运行交易对应合约的
verify方法,校验交易的输入输出、指令是否符合预设的合约规则 - 状态校验:校验输入状态未被消费、输出状态符合业务定义的参数要求
- 如需扩展自定义校验规则,可在响应流中添加自定义逻辑,比如校验交易金额是否超出节点单笔限额,所有校验通过后交易对应的状态才会存入节点的Vault账本中
任意一项校验不通过时,节点会自动拒绝该交易,不会将状态写入本地账本
内容的提问来源于stack exchange,提问作者user3930728
相关产品推荐
相关产品推荐

