如何通过Java/Node SDK完成需双组织管理员签名的链码交易?多签可行吗?
如何满足2-of-2多签名链码交易策略
当然可行!这种多签名(multisig)场景是联盟链的核心能力之一,专门用来处理需要多方授权的敏感交易。你现在的问题是仅持有Org1 Admin的凭证,缺少Org2 Admin的签名,解决思路是先生成半签名的交易提案,将其传递到Org2完成二次签名,最后合并双签名提交给网络。下面分Java和Node.js SDK分别说明具体实现步骤:
一、核心流程概述
不管用哪个SDK,核心逻辑都是一致的:
- 用Org1 Admin身份生成并签名交易提案,此时提案仅含一个签名,不满足2-of-2策略。
- 将半签名提案安全传递给Org2授权客户端,用Org2 Admin身份完成二次签名。
- 收集双签名后组装完整交易请求,提交给排序节点完成上链。
二、Java SDK 实现步骤
假设你已配置好Org1的Wallet和Gateway实例:
- 步骤1:生成半签名提案
// 从Wallet获取Org1 Admin身份 Identity org1Admin = wallet.get("org1Admin"); try (Gateway gateway = Gateway.createBuilder() .identity(org1Admin) .networkConfig(Paths.get("connection-org1.yaml")) .discovery(true) .build()) { Network network = gateway.getNetwork("mychannel"); Contract contract = network.getContract("mycc"); // 生成仅含Org1签名的交易提案 byte[] proposalBytes = contract.createTransaction("transfer") .createProposal(); // 将提案序列化后传递给Org2(可通过加密REST接口、消息队列等方式) Files.write(Paths.get("half-signed-proposal.bin"), proposalBytes); } - 步骤2:Org2端完成二次签名
在Org2的客户端中加载Admin身份,对收到的提案签名:// 读取半签名提案 byte[] proposalBytes = Files.readAllBytes(Paths.get("half-signed-proposal.bin")); Identity org2Admin = wallet.get("org2Admin"); // 解析提案并添加Org2签名 Proposal proposal = Proposal.parseFrom(proposalBytes); SignedProposal signedProposal = SignedProposal.newBuilder(proposal) .setSignature(org2Admin.sign(proposal.getProposalBytes().toByteArray())) .build(); // 将双签名提案序列化回传Org1 Files.write(Paths.get("full-signed-proposal.bin"), signedProposal.toByteArray()); - 步骤3:Org1端提交完整交易
拿到双签名提案后,提交给背书节点并完成上链:byte[] signedProposalBytes = Files.readAllBytes(Paths.get("full-signed-proposal.bin")); SignedProposal signedProposal = SignedProposal.parseFrom(signedProposalBytes); try (Gateway gateway = Gateway.createBuilder() .identity(org1Admin) .networkConfig(Paths.get("connection-org1.yaml")) .discovery(true) .build()) { Network network = gateway.getNetwork("mychannel"); Contract contract = network.getContract("mycc"); // 获取背书节点响应 Collection<ProposalResponse> responses = contract.evaluateTransaction(signedProposal); // 组装交易并提交到排序节点 byte[] transactionBytes = contract.createTransaction("transfer") .createTransaction(responses); network.submitTransaction(transactionBytes); }
三、Node.js SDK 实现步骤
基于已配置的Org1钱包和网关:
- 步骤1:生成半签名提案
const { Gateway, Wallets } = require('fabric-network'); const fs = require('fs'); const path = require('path'); async function generateHalfSignedProposal() { const wallet = await Wallets.newFileSystemWallet('./org1-wallet'); const org1Admin = await wallet.get('org1Admin'); const gateway = new Gateway(); await gateway.connect(path.resolve(__dirname, 'connection-org1.json'), { identity: org1Admin, discovery: { enabled: true, asLocalhost: true } }); const network = await gateway.getNetwork('mychannel'); const contract = network.getContract('mycc'); // 创建半签名提案并序列化保存 const proposal = await contract.createTransaction('transfer').createProposal(); fs.writeFileSync('half-signed-proposal.json', JSON.stringify(proposal.toJSON())); await gateway.disconnect(); } - 步骤2:Org2端添加签名
在Org2客户端中处理:async function addOrg2Signature() { const wallet = await Wallets.newFileSystemWallet('./org2-wallet'); const org2Admin = await wallet.get('org2Admin'); // 加载半签名提案 const proposalJson = JSON.parse(fs.readFileSync('half-signed-proposal.json', 'utf8')); const proposal = Proposal.fromJSON(proposalJson); // 添加Org2签名 const signature = await org2Admin.sign(Buffer.from(proposal.proposal_bytes)); proposal.signature = signature.toString('base64'); // 保存双签名提案回传Org1 fs.writeFileSync('full-signed-proposal.json', JSON.stringify(proposal.toJSON())); } - 步骤3:Org1端提交交易
async function submitFullTransaction() { const wallet = await Wallets.newFileSystemWallet('./org1-wallet'); const org1Admin = await wallet.get('org1Admin'); const gateway = new Gateway(); await gateway.connect(path.resolve(__dirname, 'connection-org1.json'), { identity: org1Admin, discovery: { enabled: true, asLocalhost: true } }); const network = await gateway.getNetwork('mychannel'); const contract = network.getContract('mycc'); // 加载双签名提案 const signedProposalJson = JSON.parse(fs.readFileSync('full-signed-proposal.json', 'utf8')); const signedProposal = Proposal.fromJSON(signedProposalJson); // 获取背书响应并提交交易 const responses = await contract.evaluateTransaction(signedProposal); const transaction = await contract.createTransaction('transfer').createTransaction(responses); await network.submitTransaction(transaction); await gateway.disconnect(); }
四、关键注意事项
- 传输安全性:半签名提案在Org1和Org2之间传递时,必须通过加密通道(如TLS、加密消息队列)传输,防止提案被篡改或泄露。
- 权限校验:Org2客户端需验证请求签名的交易合法性,避免为未经授权的交易签名。
- SDK版本兼容:不同Fabric SDK版本(如v2.x与v1.x)的API细节存在差异,需根据实际使用版本调整代码。
- 签名顺序无关:无论先由Org1还是Org2签名,只要最终收集到两个有效签名,即可满足2-of-2策略要求。
内容的提问来源于stack exchange,提问作者Thinker
相关产品推荐
相关产品推荐

