教程区块链区块链技术ch1515.5 Fabric SDK:Node.js 后端服务开发

本页目录

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

评论加载中…

发表评论

0/2000