Files
makemd/server/src/services/BlockchainTraceabilityService.ts

94 lines
2.8 KiB
TypeScript
Raw Normal View History

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);
}
}