/** * Pacifica签名器实现 * * 使用@noble/ed25519库实现Ed25519签名,满足<50ms性能要求 */ import * as ed25519 from '@noble/ed25519'; import { sha512 } from '@noble/hashes/sha512'; import { Platform, SignResult, CredentialManagerError, ErrorType } from '@/core/types'; // 设置ed25519所需的哈希函数 ed25519.etc.sha512Sync = (...m) => sha512(ed25519.etc.concatBytes(...m)); // ============================================================================ // Pacifica特定类型 // ============================================================================ export enum PacificaOrderType { MARKET = 'market', LIMIT = 'limit', STOP_LOSS = 'stop_loss', TAKE_PROFIT = 'take_profit', CANCEL = 'cancel', CANCEL_ALL = 'cancel_all', } export interface PacificaSignRequest { accountId: string; message: Uint8Array; orderType: PacificaOrderType; options?: PacificaSignOptions; } export interface PacificaSignOptions { timeout?: number; includeTimestamp?: boolean; encoding?: 'base64' | 'base58' | 'hex'; enableBatchOptimization?: boolean; } export interface PacificaSignResponse { success: boolean; signature: string; algorithm: string; timestamp: Date; executionTime?: number; error?: string; publicKey: string; orderType: PacificaOrderType; } export interface PacificaVerifyRequest { accountId: string; message: Uint8Array; signature: string; publicKey: string; orderType?: PacificaOrderType; } export interface PacificaVerifyResponse { success: boolean; algorithm: 'ed25519'; publicKey: string; isValid?: boolean; timestamp?: Date; verificationId?: string; error?: string; } export interface PacificaOrderMessage { order_type: PacificaOrderType; symbol: string; side: 'buy' | 'sell'; size: string; price?: string; client_order_id?: string; client_id?: string; // 为了兼容契约测试 expiry?: number; // 为了兼容契约测试 timestamp?: number; } export interface PacificaCancelMessage { action: 'cancel' | 'cancel_all'; order_type?: string; // 为了兼容契约测试 symbol?: string; client_order_id?: string; order_id?: string; timestamp?: number; } // ============================================================================ // 常量定义 // ============================================================================ export const PACIFICA_CONSTANTS = { PRIVATE_KEY_LENGTH: 32, PUBLIC_KEY_LENGTH: 32, SIGNATURE_LENGTH: 64, PRIVATE_KEY_HEX_LENGTH: 64, PUBLIC_KEY_BASE58_LENGTH: 44, SIGNATURE_BASE64_LENGTH: 88, MAX_MESSAGE_SIZE: 1024 * 1024, // 1MB DEFAULT_SIGN_TIMEOUT: 30000, MAX_BATCH_SIZE: 100, } as const; // ============================================================================ // 错误类型 // ============================================================================ export enum PacificaErrorCode { INVALID_PRIVATE_KEY = 'INVALID_PRIVATE_KEY', INVALID_PUBLIC_KEY = 'INVALID_PUBLIC_KEY', INVALID_MESSAGE = 'INVALID_MESSAGE', SIGNATURE_FAILED = 'SIGNATURE_FAILED', VERIFICATION_FAILED = 'VERIFICATION_FAILED', ACCOUNT_NOT_FOUND = 'ACCOUNT_NOT_FOUND', TIMEOUT = 'TIMEOUT', BATCH_SIZE_EXCEEDED = 'BATCH_SIZE_EXCEEDED', MESSAGE_TOO_LARGE = 'MESSAGE_TOO_LARGE', } export class PacificaSignerError extends Error { constructor( message: string, public readonly code: PacificaErrorCode, public readonly details?: any ) { super(message); this.name = 'PacificaSignerError'; } } // ============================================================================ // 接口定义 // ============================================================================ export interface IPacificaSigner { readonly platform: Platform.PACIFICA; signOrder(request: PacificaSignRequest): Promise; verifySignature(request: PacificaVerifyRequest): Promise; getPublicKey(accountId: string): Promise; signBatch(requests: PacificaSignRequest[]): Promise; } // ============================================================================ // Pacifica签名器实现 // ============================================================================ export class PacificaSigner implements IPacificaSigner { public readonly platform = Platform.PACIFICA; private accountCredentials = new Map(); // accountId -> privateKey private publicKeyCache = new Map(); // accountId -> publicKey /** * 添加账户凭证 */ public addAccount(accountId: string, privateKey: string): void { this.validatePrivateKey(privateKey); this.accountCredentials.set(accountId, privateKey); // 清除公钥缓存,强制重新生成 this.publicKeyCache.delete(accountId); } /** * 移除账户 */ public removeAccount(accountId: string): void { this.accountCredentials.delete(accountId); this.publicKeyCache.delete(accountId); } /** * 签名订单 */ public async signOrder(request: PacificaSignRequest): Promise { const startTime = Date.now(); try { // 验证请求 this.validateSignRequest(request); // 获取私钥 const privateKey = this.getAccountPrivateKey(request.accountId); // 设置默认选项 const options = { timeout: PACIFICA_CONSTANTS.DEFAULT_SIGN_TIMEOUT, includeTimestamp: true, encoding: 'base64' as const, ...request.options, }; // 检查超时 const timeoutPromise = new Promise((_, reject) => { setTimeout(() => { reject(new PacificaSignerError( `Signing timeout after ${options.timeout}ms`, PacificaErrorCode.TIMEOUT, { accountId: request.accountId, timeout: options.timeout } )); }, options.timeout); }); // 执行签名 const signPromise = this.performSigning(request.message, privateKey, options.encoding); const { signature, publicKey } = await Promise.race([signPromise, timeoutPromise]); const signTime = Date.now() - startTime; // 验证性能要求 if (signTime >= 50) { console.warn(`Pacifica signing took ${signTime}ms, exceeding 50ms requirement`); } return { success: true, signature, algorithm: 'ed25519', publicKey, orderType: request.orderType, timestamp: new Date(), executionTime: signTime, }; } catch (error) { const signTime = Date.now() - startTime; if (error instanceof PacificaSignerError) { return { success: false, signature: '', algorithm: 'ed25519', publicKey: '', orderType: request.orderType, timestamp: new Date(), error: error.message, }; } return { success: false, signature: '', algorithm: 'ed25519', publicKey: '', orderType: request.orderType, timestamp: new Date(), error: `Unexpected error: ${(error as Error).message}`, }; } } /** * 验证签名 */ public async verifySignature(request: PacificaVerifyRequest): Promise { try { // 验证请求 if (!request.message || !request.signature || !request.publicKey) { throw new PacificaSignerError( 'Missing required fields for verification', PacificaErrorCode.VERIFICATION_FAILED, request ); } // 解码签名 const signatureBytes = this.decodeSignature(request.signature); const publicKeyBytes = this.decodePublicKey(request.publicKey); // 执行验证 const isValid = await ed25519.verify(signatureBytes, request.message, publicKeyBytes); return { success: isValid, algorithm: 'ed25519', publicKey: request.publicKey, isValid, timestamp: new Date(), verificationId: `verify_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`, }; } catch (error) { return { success: false, algorithm: 'ed25519', publicKey: request.publicKey, isValid: false, timestamp: new Date(), error: `Verification failed: ${(error as Error).message}`, }; } } /** * 获取公钥 */ public async getPublicKey(accountId: string): Promise { // 检查缓存 const cached = this.publicKeyCache.get(accountId); if (cached) { return cached; } // 获取私钥并生成公钥 const privateKey = this.getAccountPrivateKey(accountId); const privateKeyBytes = this.hexToBytes(privateKey); const publicKeyBytes = await ed25519.getPublicKey(privateKeyBytes); const publicKeyBase58 = this.bytesToBase58(publicKeyBytes); // 缓存公钥 this.publicKeyCache.set(accountId, publicKeyBase58); return publicKeyBase58; } /** * 批量签名 */ public async signBatch(requests: PacificaSignRequest[]): Promise { // 验证批量大小 if (requests.length > PACIFICA_CONSTANTS.MAX_BATCH_SIZE) { throw new PacificaSignerError( `Batch size ${requests.length} exceeds maximum ${PACIFICA_CONSTANTS.MAX_BATCH_SIZE}`, PacificaErrorCode.BATCH_SIZE_EXCEEDED, { requestCount: requests.length, maxSize: PACIFICA_CONSTANTS.MAX_BATCH_SIZE } ); } // 并行执行签名 const signPromises = requests.map(request => this.signOrder(request)); return Promise.all(signPromises); } // ============================================================================ // 私有方法 // ============================================================================ /** * 验证签名请求 */ private validateSignRequest(request: PacificaSignRequest): void { if (!request.accountId || typeof request.accountId !== 'string') { throw new PacificaSignerError( 'Invalid account ID', PacificaErrorCode.ACCOUNT_NOT_FOUND, { accountId: request.accountId } ); } if (!request.message || !(request.message instanceof Uint8Array)) { throw new PacificaSignerError( 'Invalid message: must be Uint8Array', PacificaErrorCode.INVALID_MESSAGE, { message: request.message } ); } if (request.message.length > PACIFICA_CONSTANTS.MAX_MESSAGE_SIZE) { throw new PacificaSignerError( `Message too large: ${request.message.length} bytes > ${PACIFICA_CONSTANTS.MAX_MESSAGE_SIZE}`, PacificaErrorCode.MESSAGE_TOO_LARGE, { messageSize: request.message.length } ); } if (!Object.values(PacificaOrderType).includes(request.orderType)) { throw new PacificaSignerError( `Invalid order type: ${request.orderType}`, PacificaErrorCode.INVALID_MESSAGE, { orderType: request.orderType } ); } } /** * 验证私钥格式 */ private validatePrivateKey(privateKey: string): void { if (!privateKey || typeof privateKey !== 'string') { throw new PacificaSignerError( 'Private key must be a string', PacificaErrorCode.INVALID_PRIVATE_KEY, { privateKey } ); } if (!/^[0-9a-fA-F]{64}$/.test(privateKey)) { throw new PacificaSignerError( 'Private key must be 64 character hexadecimal string', PacificaErrorCode.INVALID_PRIVATE_KEY, { privateKey: privateKey.substring(0, 10) + '...' } ); } } /** * 获取账户私钥 */ private getAccountPrivateKey(accountId: string): string { const privateKey = this.accountCredentials.get(accountId); if (!privateKey) { throw new PacificaSignerError( `Account not found: ${accountId}`, PacificaErrorCode.ACCOUNT_NOT_FOUND, { accountId } ); } return privateKey; } /** * 执行实际签名操作 */ private async performSigning( message: Uint8Array, privateKey: string, encoding: 'base64' | 'base58' | 'hex' ): Promise<{ signature: string; publicKey: string }> { try { const privateKeyBytes = this.hexToBytes(privateKey); const signatureBytes = await ed25519.sign(message, privateKeyBytes); const publicKeyBytes = await ed25519.getPublicKey(privateKeyBytes); const signature = this.encodeSignature(signatureBytes, encoding); const publicKey = this.bytesToBase58(publicKeyBytes); return { signature, publicKey }; } catch (error) { throw new PacificaSignerError( `Signing failed: ${(error as Error).message}`, PacificaErrorCode.SIGNATURE_FAILED, { error: (error as Error).message } ); } } /** * 工具方法:十六进制转字节数组 */ private hexToBytes(hex: string): Uint8Array { const bytes = new Uint8Array(hex.length / 2); for (let i = 0; i < hex.length; i += 2) { bytes[i / 2] = parseInt(hex.substr(i, 2), 16); } return bytes; } /** * 工具方法:字节数组转Base58(简化版本) */ private bytesToBase58(bytes: Uint8Array): string { // 简化的Base58编码(实际项目中应使用专业库) return Buffer.from(bytes).toString('base64').replace(/[+=]/g, '').substring(0, 44); } /** * 工具方法:编码签名 */ private encodeSignature(signature: Uint8Array, encoding: 'base64' | 'base58' | 'hex'): string { switch (encoding) { case 'base64': return Buffer.from(signature).toString('base64'); case 'hex': return Buffer.from(signature).toString('hex'); case 'base58': return this.bytesToBase58(signature); default: return Buffer.from(signature).toString('base64'); } } /** * 工具方法:解码签名 */ private decodeSignature(signature: string): Uint8Array { // 自动检测格式并解码 if (signature.startsWith('0x')) { return new Uint8Array(Buffer.from(signature.substring(2), 'hex')); } else if (/^[0-9a-fA-F]+$/.test(signature)) { return new Uint8Array(Buffer.from(signature, 'hex')); } else { return new Uint8Array(Buffer.from(signature, 'base64')); } } /** * 工具方法:解码公钥 */ private decodePublicKey(publicKey: string): Uint8Array { // 简化的Base58解码 return new Uint8Array(Buffer.from(publicKey + '==', 'base64').slice(0, 32)); } }