94 lines
2.8 KiB
TypeScript
94 lines
2.8 KiB
TypeScript
|
|
import * as crypto from 'crypto';
|
|||
|
|
import { logger } from '../utils/logger';
|
|||
|
|
|
|||
|
|
export interface BlockchainBlock {
|
|||
|
|
index: number;
|
|||
|
|
timestamp: Date;
|
|||
|
|
data: any;
|
|||
|
|
previousHash: string;
|
|||
|
|
hash: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* [BIZ_TRADE_11] 基于区块链的供应链溯源集成 (Blockchain Traceability)
|
|||
|
|
* @description 实现全链路关键节点的不可篡改存证,支持商品从工厂、口岸到终端用户的全流程可信溯源
|
|||
|
|
*/
|
|||
|
|
export class BlockchainTraceabilityService {
|
|||
|
|
private static chain: BlockchainBlock[] = [];
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 初始化区块链
|
|||
|
|
*/
|
|||
|
|
static async init() {
|
|||
|
|
if (this.chain.length === 0) {
|
|||
|
|
const genesisBlock = this.createBlock(0, '0', { message: 'Genesis Block' });
|
|||
|
|
this.chain.push(genesisBlock);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 记录溯源存证 (Evidence)
|
|||
|
|
* @param eventType 事件类型 (e.g., 'MANUFACTURE', 'CUSTOMS_CLEARANCE', 'DELIVERY')
|
|||
|
|
* @param details 详细数据
|
|||
|
|
*/
|
|||
|
|
static async recordEvidence(eventType: string, details: any): Promise<string> {
|
|||
|
|
logger.info(`[Blockchain] Recording evidence for event: ${eventType}`);
|
|||
|
|
|
|||
|
|
const previousBlock = this.chain[this.chain.length - 1];
|
|||
|
|
const newBlock = this.createBlock(
|
|||
|
|
this.chain.length,
|
|||
|
|
previousBlock.hash,
|
|||
|
|
{ eventType, details, timestamp: new Date().toISOString() }
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
this.chain.push(newBlock);
|
|||
|
|
logger.info(`[Blockchain] Evidence recorded. Block Hash: ${newBlock.hash}`);
|
|||
|
|
|
|||
|
|
return newBlock.hash;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 验证全链完整性
|
|||
|
|
*/
|
|||
|
|
static async verifyChain(): Promise<boolean> {
|
|||
|
|
for (let i = 1; i < this.chain.length; i++) {
|
|||
|
|
const current = this.chain[i];
|
|||
|
|
const previous = this.chain[i - 1];
|
|||
|
|
|
|||
|
|
// 1. 校验当前哈希
|
|||
|
|
const recalculatedHash = this.calculateHash(current.index, current.previousHash, current.timestamp, current.data);
|
|||
|
|
if (current.hash !== recalculatedHash) return false;
|
|||
|
|
|
|||
|
|
// 2. 校验哈希链
|
|||
|
|
if (current.previousHash !== previous.hash) return false;
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 构造区块
|
|||
|
|
*/
|
|||
|
|
private static createBlock(index: number, previousHash: string, data: any): BlockchainBlock {
|
|||
|
|
const timestamp = new Date();
|
|||
|
|
const hash = this.calculateHash(index, previousHash, timestamp, data);
|
|||
|
|
return { index, timestamp, data, previousHash, hash };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 计算哈希 (SHA-256)
|
|||
|
|
*/
|
|||
|
|
private static calculateHash(index: number, previousHash: string, timestamp: Date, data: any): string {
|
|||
|
|
const str = `${index}${previousHash}${timestamp.toISOString()}${JSON.stringify(data)}`;
|
|||
|
|
return crypto.createHash('sha256').update(str).digest('hex');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 查询溯源历史
|
|||
|
|
*/
|
|||
|
|
static async getHistory(productId: string): Promise<any[]> {
|
|||
|
|
return this.chain
|
|||
|
|
.filter(block => block.data?.details?.productId === productId)
|
|||
|
|
.map(block => block.data);
|
|||
|
|
}
|
|||
|
|
}
|