Fabric v2.4+ 推出了 Gateway API,将复杂的背书、排序、事件监听封装为高层接口。Node.js 后端只需连接一个 gateway peer,其他自动处理。
15.5.1 连接模型
graph LR
App[Node.js 后端应用] --> Gateway[Fabric Gateway]
Gateway --> P1[peer0.org1]
P1 --> P2[peer0.org2] & O[orderer]
P2 --> O
style App fill:#e8f5e9
style Gateway fill:#e3f2fd
Gateway vs 旧版 SDK
| 能力 | 旧版 SDK (v1.x) | Gateway (v2.4+) |
|---|---|---|
| 连接 | 直连所有背书节点 | 单点 gateway peer |
| 背书 | 客户端手动组装 | 内部自动分发 |
| 提交 | 手动调用 orderer | 自动处理 |
| 监听 | 需独立事件服务 | 简化 |
| 证书 | 每个节点一个连接 | peer 内部转发 |
15.5.2 后端服务代码骨架
typescript
/**
* Fabric Gateway Node.js 后端
* 将链码调用映射为 REST API
*/
import { Gateway, Wallets, Contract } from 'fabric-gateway';
import * as grpc from '@grpc/grpc-js';
import { readFileSync } from 'fs';
interface ConnectionProfile {
url: string;
tlsCACert: string;
peerName: string;
}
class FabricClientService {
private gateway: Gateway;
private contract: Contract;
async connect(profile: ConnectionProfile, userId: string, org: string) {
// 加载 TLS 根证书
const tlsRootCert = readFileSync(profile.tlsCACert);
const client = new grpc.Channel(profile.url, grpc.credentials.createSsl(Buffer.from(tlsRootCert)));
// 加载用户身份钱包
const wallet = await Wallets.newFileSystemWallet('./wallet');
const identity = await wallet.get(userId);
if (!identity) throw new Error(`身份 ${userId} 不存在于钱包`);
// 建立 Gateway 连接
const gateway = new Gateway()// 内部使用 gRPC
// 通过 gateway 获取网络与合约
this.gateway = gateway;
const network = gateway.getNetwork('mychannel');
this.contract = network.getContract('assettransfer');
}
// === 只读查询:evaluate(单个 peer)
async getAsset(id: string): Promise<Asset> {
const result = await this.contract.evaluateTransaction('ReadAsset', id);
return JSON.parse(Buffer.from(result).toString());
}
// === 写入交易:submit(完整背书→排序→提交)
async createAsset(asset: Asset): Promise<string> {
const result = await this.contract.submitTransaction(
'CreateAsset',
asset.id,
asset.color,
asset.owner,
asset.size.toString(),
asset.appraisedValue.toString(),
);
// 返回交易 ID
return Buffer.from(result).toString();
}
// 转移(需要写交易)
async transferAsset(id: string, newOwner: string): Promise<string> {
return this.contract.submitTransaction('TransferAsset', id, newOwner)
.then(r => Buffer.from(r).toString());
}
async disconnect() {
this.gateway.close();
}
}
// Express REST API 封装
import express from 'express';
const app = express();
const fabric = new FabricClientService();
app.get('/assets/:id', async (req, res) => {
const asset = await fabric.getAsset(req.params.id);
res.json(asset);
});
app.post('/assets', async (req, res) => {
const txId = await fabric.createAsset(req.body);
res.json({ transactionId: txId, status: 'submitted' });
});
app.put('/assets/:id/transfer', async (req, res) => {
const txId = await fabric.transferAsset(req.params.id, req.body.newOwner);
res.json({ transactionId: txId });
});
// 对比:公链中用户用 MetaMask 签名
// 联盟链中后端代签(因为是服务端服务)
// 后端持有用户注册的钱包密钥(或 HSM 托管)15.5.3 Evaluate vs Submit
| 方法 | 用途 | 调用链 | 性能 |
|---|---|---|---|
evaluateTransaction | 只读查询 | 单个 peer 模拟 → 返回 | 快 |
submitTransaction | 写交易 | 全背书 → 排序 → 提交 | 慢(秒级) |
15.5.4 身份与密钥管理
graph TD
subgraph Dev["开发"]
D1[本地文件系统钱包]
end
subgraph Prod["生产"]
P1[硬件安全模块 HSM]
P2[HashiCorp Vault]
P3[AWS KMS / Azure Key Vault]
end
D1 -.升级.-> P1
D1 -.或.-> P2
D1 -.或.-> P3
style P1 fill:#e8f5e9
style P2 fill:#e8f5e9
style P3 fill:#e8f5e9
> ← 15.4 生命周期管理 | 前往 → 15.6 前端界面设计 |*
评论
0评论加载中…