/** * Pacifica签名器契约测试 * * 验证IPacificaSigner接口的契约实现 * 测试Ed25519签名、批量操作、消息序列化等Pacifica特定功能 */ import { describe, test, expect, beforeEach, afterEach } from '@jest/globals'; import { PacificaSigner, PacificaSignRequest, PacificaSignResponse, PacificaVerifyRequest, PacificaOrderType, PacificaOrderMessage, PacificaCancelMessage, PACIFICA_CONSTANTS, Platform, SignResult } from '../../src/index'; describe('IPacificaSigner Contract Tests', () => { let signer: PacificaSigner; const testAccountId = 'pacifica-signer-test-001'; beforeEach(async () => { // 创建PacificaSigner实例并添加测试账户 const { PacificaSigner } = await import('../../src/platforms/pacifica/PacificaSigner'); signer = new PacificaSigner(); // 添加测试账户私钥(64字符十六进制) const testPrivateKey = '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'; signer.addAccount(testAccountId, testPrivateKey); }); afterEach(async () => { // 清理资源 }); describe('平台接口验证', () => { test('应该正确标识Pacifica平台', () => { expect(signer.platform).toBe(Platform.PACIFICA); }); }); describe('Ed25519签名功能', () => { test('应该能对Pacifica订单进行签名', async () => { const orderMessage: PacificaOrderMessage = { order_type: PacificaOrderType.LIMIT, symbol: 'BTC-USD', side: 'buy', size: '0.001', price: '65000.00', client_id: 'test-order-001', timestamp: Date.now(), expiry: Date.now() + 300000 }; const messageBytes = new TextEncoder().encode(JSON.stringify(orderMessage)); const request: PacificaSignRequest = { accountId: testAccountId, message: messageBytes, orderType: PacificaOrderType.LIMIT, options: { timeout: 30000, includeTimestamp: true, encoding: 'base64' } }; const response = await signer.signOrder(request); expect(response.success).toBe(true); expect(response.signature).toBeDefined(); expect(response.signature.length).toBe(PACIFICA_CONSTANTS.SIGNATURE_BASE64_LENGTH); expect(response.algorithm).toBe('ed25519'); expect(response.publicKey).toBeDefined(); expect(response.publicKey.length).toBe(PACIFICA_CONSTANTS.PUBLIC_KEY_BASE58_LENGTH); expect(response.orderType).toBe(PacificaOrderType.LIMIT); expect(response.timestamp).toBeInstanceOf(Date); expect(response.executionTime).toBeLessThan(50); // NFR-002: <50ms }); test('应该能对市价单进行签名', async () => { const orderMessage: PacificaOrderMessage = { order_type: PacificaOrderType.MARKET, symbol: 'ETH-USD', side: 'sell', size: '0.1', client_id: 'market-order-001', timestamp: Date.now() }; const messageBytes = new TextEncoder().encode(JSON.stringify(orderMessage)); const request: PacificaSignRequest = { accountId: testAccountId, message: messageBytes, orderType: PacificaOrderType.MARKET }; const response = await signer.signOrder(request); expect(response.success).toBe(true); expect(response.algorithm).toBe('ed25519'); expect(response.orderType).toBe(PacificaOrderType.MARKET); }); test('应该能对取消订单进行签名', async () => { const cancelMessage: PacificaCancelMessage = { action: 'cancel', order_type: 'cancel', order_id: 'order-to-cancel-123', timestamp: Date.now() }; const messageBytes = new TextEncoder().encode(JSON.stringify(cancelMessage)); const request: PacificaSignRequest = { accountId: testAccountId, message: messageBytes, orderType: PacificaOrderType.CANCEL }; const response = await signer.signOrder(request); expect(response.success).toBe(true); expect(response.orderType).toBe(PacificaOrderType.CANCEL); }); }); describe('签名验证功能', () => { test('应该能验证有效的Ed25519签名', async () => { // 首先创建一个签名 const orderMessage: PacificaOrderMessage = { order_type: PacificaOrderType.LIMIT, symbol: 'BTC-USD', side: 'buy', size: '0.001', price: '65000.00', client_id: 'verify-test-001', timestamp: Date.now() }; const messageBytes = new TextEncoder().encode(JSON.stringify(orderMessage)); const signResponse = await signer.signOrder({ accountId: testAccountId, message: messageBytes, orderType: PacificaOrderType.LIMIT }); expect(signResponse.success).toBe(true); // 然后验证签名 const verifyRequest: PacificaVerifyRequest = { accountId: testAccountId, message: messageBytes, signature: signResponse.signature, publicKey: signResponse.publicKey, orderType: PacificaOrderType.LIMIT }; const verifyResponse = await signer.verifySignature(verifyRequest); expect(verifyResponse.success).toBe(true); expect(verifyResponse.isValid).toBe(true); expect(verifyResponse.algorithm).toBe('ed25519'); expect(verifyResponse.publicKey).toBe(signResponse.publicKey); expect(verifyResponse.timestamp).toBeInstanceOf(Date); expect(verifyResponse.verificationId).toBeDefined(); }); test('应该拒绝被篡改的消息签名', async () => { // 创建原始签名 const originalMessage = new TextEncoder().encode('original message'); const signResponse = await signer.signOrder({ accountId: testAccountId, message: originalMessage, orderType: PacificaOrderType.MARKET }); // 尝试验证不同的消息(篡改) const tamperedMessage = new TextEncoder().encode('tampered message'); const verifyRequest: PacificaVerifyRequest = { accountId: testAccountId, message: tamperedMessage, signature: signResponse.signature, publicKey: signResponse.publicKey }; const verifyResponse = await signer.verifySignature(verifyRequest); expect(verifyResponse.success).toBe(true); // 验证操作成功 expect(verifyResponse.isValid).toBe(false); // 但签名无效 }); test('应该拒绝无效格式的签名', async () => { const message = new TextEncoder().encode('test message'); const verifyRequest: PacificaVerifyRequest = { accountId: testAccountId, message: message, signature: 'invalid-signature-format', publicKey: 'valid-looking-public-key-base58' }; const verifyResponse = await signer.verifySignature(verifyRequest); expect(verifyResponse.success).toBe(false); expect(verifyResponse.error).toBeDefined(); expect(verifyResponse.error).toContain('INVALID'); }); }); describe('公钥管理', () => { test('应该能获取账户公钥', async () => { const publicKey = await signer.getPublicKey(testAccountId); expect(publicKey).toBeDefined(); expect(typeof publicKey).toBe('string'); expect(publicKey.length).toBe(PACIFICA_CONSTANTS.PUBLIC_KEY_BASE58_LENGTH); // 验证Base58格式(基本检查) expect(/^[1-9A-HJ-NP-Za-km-z]+$/.test(publicKey)).toBe(true); }); test('应该为不存在的账户返回错误', async () => { await expect(signer.getPublicKey('non-existent-account')) .rejects.toThrow('ACCOUNT_NOT_FOUND'); }); }); describe('批量签名功能', () => { test('应该能执行批量签名操作', async () => { const orders: PacificaOrderMessage[] = [ { order_type: PacificaOrderType.LIMIT, symbol: 'BTC-USD', side: 'buy', size: '0.001', price: '65000.00', client_id: 'batch-order-1', timestamp: Date.now() }, { order_type: PacificaOrderType.MARKET, symbol: 'ETH-USD', side: 'sell', size: '0.1', client_id: 'batch-order-2', timestamp: Date.now() }, { action: 'cancel', order_type: PacificaOrderType.CANCEL, order_id: 'order-to-cancel', timestamp: Date.now(), side: 'buy', // Add required fields for compatibility size: '0' } as any ]; const requests: PacificaSignRequest[] = orders.map((order, index) => ({ accountId: testAccountId, message: new TextEncoder().encode(JSON.stringify(order)), orderType: order.order_type as PacificaOrderType })); const startTime = Date.now(); const responses = await signer.signBatch(requests); const totalTime = Date.now() - startTime; expect(responses).toHaveLength(requests.length); expect(totalTime).toBeLessThan(300); // 批量操作应该在300ms内完成 responses.forEach((response, index) => { expect(response.success).toBe(true); expect(response.signature).toBeDefined(); expect(response.algorithm).toBe('ed25519'); expect(response.orderType).toBe(orders[index]?.order_type); expect(response.executionTime).toBeLessThan(50); }); // 验证所有签名都是唯一的 const signatures = responses.map(r => r.signature); const uniqueSignatures = new Set(signatures); expect(uniqueSignatures.size).toBe(signatures.length); }); test('应该拒绝超过最大批量大小的请求', async () => { const requests: PacificaSignRequest[] = Array.from( { length: PACIFICA_CONSTANTS.MAX_BATCH_SIZE + 1 }, (_, index) => ({ accountId: testAccountId, message: new TextEncoder().encode(`batch message ${index}`), orderType: PacificaOrderType.MARKET }) ); await expect(signer.signBatch(requests)) .rejects.toThrow('BATCH_SIZE_EXCEEDED'); }); test('应该处理批量请求中的部分失败', async () => { const requests: PacificaSignRequest[] = [ { accountId: testAccountId, message: new TextEncoder().encode('valid message 1'), orderType: PacificaOrderType.LIMIT }, { accountId: 'invalid-account', message: new TextEncoder().encode('valid message 2'), orderType: PacificaOrderType.MARKET }, { accountId: testAccountId, message: new TextEncoder().encode('valid message 3'), orderType: PacificaOrderType.CANCEL } ]; const responses = await signer.signBatch(requests); expect(responses).toHaveLength(3); expect(responses[0]?.success).toBe(true); expect(responses[1]?.success).toBe(false); expect(responses[1]?.error).toContain('ACCOUNT_NOT_FOUND'); expect(responses[2]?.success).toBe(true); }); }); describe('签名选项和编码', () => { test('应该支持不同的签名编码格式', async () => { const message = new TextEncoder().encode('encoding test message'); const encodings: Array<'base64' | 'base58' | 'hex'> = ['base64', 'base58', 'hex']; for (const encoding of encodings) { const request: PacificaSignRequest = { accountId: testAccountId, message: message, orderType: PacificaOrderType.MARKET, options: { encoding } }; const response = await signer.signOrder(request); expect(response.success).toBe(true); expect(response.signature).toBeDefined(); // 验证编码格式 switch (encoding) { case 'base64': expect(/^[A-Za-z0-9+/]+=*$/.test(response.signature)).toBe(true); break; case 'base58': expect(/^[1-9A-HJ-NP-Za-km-z]+$/.test(response.signature)).toBe(true); break; case 'hex': expect(/^[0-9a-fA-F]+$/.test(response.signature)).toBe(true); break; } } }); test('应该支持时间戳包含选项', async () => { const message = new TextEncoder().encode('timestamp test message'); // 包含时间戳 const withTimestamp = await signer.signOrder({ accountId: testAccountId, message: message, orderType: PacificaOrderType.LIMIT, options: { includeTimestamp: true } }); // 不包含时间戳 const withoutTimestamp = await signer.signOrder({ accountId: testAccountId, message: message, orderType: PacificaOrderType.LIMIT, options: { includeTimestamp: false } }); expect(withTimestamp.success).toBe(true); expect(withoutTimestamp.success).toBe(true); // 签名应该不同(因为时间戳的存在) expect(withTimestamp.signature).not.toBe(withoutTimestamp.signature); }); test('应该遵守签名超时设置', async () => { const message = new TextEncoder().encode('timeout test message'); // 极短超时应该失败 const shortTimeoutRequest: PacificaSignRequest = { accountId: testAccountId, message: message, orderType: PacificaOrderType.MARKET, options: { timeout: 1 } // 1ms }; const response = await signer.signOrder(shortTimeoutRequest); expect(response.success).toBe(false); expect(response.error).toContain('TIMEOUT'); }); }); describe('消息大小限制', () => { test('应该拒绝过大的消息', async () => { // 创建超过最大大小的消息 const largeMessage = new Uint8Array(PACIFICA_CONSTANTS.MAX_MESSAGE_SIZE + 1); largeMessage.fill(65); // 填充'A'字符 const request: PacificaSignRequest = { accountId: testAccountId, message: largeMessage, orderType: PacificaOrderType.MARKET }; const response = await signer.signOrder(request); expect(response.success).toBe(false); expect(response.error).toContain('MESSAGE_TOO_LARGE'); }); test('应该接受最大大小以内的消息', async () => { // 创建恰好最大大小的消息 const maxSizeMessage = new Uint8Array(PACIFICA_CONSTANTS.MAX_MESSAGE_SIZE); maxSizeMessage.fill(65); const request: PacificaSignRequest = { accountId: testAccountId, message: maxSizeMessage, orderType: PacificaOrderType.MARKET }; const response = await signer.signOrder(request); expect(response.success).toBe(true); expect(response.signature).toBeDefined(); }); }); describe('错误处理和边界条件', () => { test('应该处理空消息', async () => { const emptyMessage = new Uint8Array(0); const request: PacificaSignRequest = { accountId: testAccountId, message: emptyMessage, orderType: PacificaOrderType.MARKET }; const response = await signer.signOrder(request); expect(response.success).toBe(false); expect(response.error).toContain('INVALID_MESSAGE'); }); test('应该处理无效的订单类型', async () => { const message = new TextEncoder().encode('test message'); const request: PacificaSignRequest = { accountId: testAccountId, message: message, orderType: 'invalid_order_type' as any }; const response = await signer.signOrder(request); expect(response.success).toBe(false); expect(response.error).toContain('INVALID_ORDER_TYPE'); }); test('应该在并发场景下保持稳定', async () => { const message = new TextEncoder().encode('concurrent test message'); const concurrentRequests = 20; const promises = Array.from({ length: concurrentRequests }, (_, index) => signer.signOrder({ accountId: testAccountId, message: message, orderType: PacificaOrderType.MARKET }) ); const results = await Promise.all(promises); results.forEach((result, index) => { expect(result.success).toBe(true); expect(result.signature).toBeDefined(); expect(result.executionTime).toBeLessThan(50); }); // 验证所有签名都是唯一的 const signatures = results.map(r => r.signature); const uniqueSignatures = new Set(signatures); expect(uniqueSignatures.size).toBe(signatures.length); }); }); });