UNPKG

@covenance/dlc

Version:

Crypto and Bitcoin functions for Covenance DLC implementation

180 lines (161 loc) 6.41 kB
import { expect } from 'chai'; import { Point, utils } from '../src/crypto/secp256k1'; import { hexToBytes, bytesToHex, pointToHex, hexToPoint, signatureToHex, hexToSignature, adaptorSignatureToHex, hexToAdaptorSignature, sha256, sha256Hex, be32 } from '../src/utils'; import { Signature, AdaptorSignature } from '../src/crypto/types'; describe('Utility Functions', () => { describe('hexToBytes and bytesToHex', () => { it('should convert between hex strings and bytes correctly', () => { const hex = '0123456789abcdef'; const bytes = hexToBytes(hex); expect(bytesToHex(bytes)).to.equal(hex); }); it('should handle empty hex string', () => { const hex = ''; const bytes = hexToBytes(hex); expect(bytes.length).to.equal(0); expect(bytesToHex(bytes)).to.equal(''); }); it('should handle zero bytes', () => { const hex = '00000000'; const bytes = hexToBytes(hex); expect(bytes.length).to.equal(4); expect(bytesToHex(bytes)).to.equal(hex); }); }); describe('pointToHex and hexToPoint', () => { it('should convert between Points and hex strings correctly', () => { const point = Point.fromPrivateKey(utils.randomPrivateKey()); const hex = pointToHex(point); const point2 = hexToPoint(hex); expect(point2.equals(point)).to.be.true; }); it('should handle generator point', () => { const point = Point.BASE; const hex = pointToHex(point); const point2 = hexToPoint(hex); expect(point2.equals(point)).to.be.true; }); it('should throw error for invalid point hex', () => { expect(() => hexToPoint('00')).to.throw(); }); }); describe('signatureToHex and hexToSignature', () => { it('should convert between Signatures and hex strings correctly', () => { const sig: Signature = { R: Point.fromPrivateKey(utils.randomPrivateKey()), s: BigInt('123456789') }; const hex = signatureToHex(sig); const sig2 = hexToSignature(hex); expect(sig2.R.equals(sig.R)).to.be.true; expect(sig2.s).to.equal(sig.s); }); it('should handle zero s value', () => { const sig: Signature = { R: Point.fromPrivateKey(utils.randomPrivateKey()), s: BigInt(0) }; const hex = signatureToHex(sig); const sig2 = hexToSignature(hex); expect(sig2.R.equals(sig.R)).to.be.true; expect(sig2.s).to.equal(sig.s); }); it('should handle large s values', () => { const sig: Signature = { R: Point.fromPrivateKey(utils.randomPrivateKey()), s: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') }; const hex = signatureToHex(sig); const sig2 = hexToSignature(hex); expect(sig2.R.equals(sig.R)).to.be.true; expect(sig2.s).to.equal(sig.s); }); }); describe('adaptorSignatureToHex and hexToAdaptorSignature', () => { it('should convert between AdaptorSignatures and hex strings correctly', () => { const sig: AdaptorSignature = { R_prime: Point.fromPrivateKey(utils.randomPrivateKey()), s_prime: BigInt('987654321') }; const hex = adaptorSignatureToHex(sig); const sig2 = hexToAdaptorSignature(hex); expect(sig2.R_prime.equals(sig.R_prime)).to.be.true; expect(sig2.s_prime).to.equal(sig.s_prime); }); it('should handle zero s_prime value', () => { const sig: AdaptorSignature = { R_prime: Point.fromPrivateKey(utils.randomPrivateKey()), s_prime: BigInt(0) }; const hex = adaptorSignatureToHex(sig); const sig2 = hexToAdaptorSignature(hex); expect(sig2.R_prime.equals(sig.R_prime)).to.be.true; expect(sig2.s_prime).to.equal(sig.s_prime); }); it('should handle large s_prime values', () => { const sig: AdaptorSignature = { R_prime: Point.fromPrivateKey(utils.randomPrivateKey()), s_prime: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') }; const hex = adaptorSignatureToHex(sig); const sig2 = hexToAdaptorSignature(hex); expect(sig2.R_prime.equals(sig.R_prime)).to.be.true; expect(sig2.s_prime).to.equal(sig.s_prime); }); }); describe('sha256 and sha256Hex', () => { it('should compute correct SHA256 hash', async () => { const message = new Uint8Array([1, 2, 3, 4, 5]); const hash = await sha256(message); expect(hash).to.be.instanceOf(Uint8Array); expect(hash.length).to.equal(32); }); it('should compute correct SHA256 hash from hex string', async () => { const hex = '0102030405'; const hash = await sha256Hex(hex); expect(hash).to.be.a('string'); expect(hash.length).to.equal(64); }); }); describe('be32', () => { it('should write a typical number correctly', () => { const arr = new Uint8Array(32); be32(arr, 0, BigInt('0x1234567890abcdef')); expect(bytesToHex(arr)).to.equal('0000000000000000000000000000000000000000000000001234567890abcdef'); }); it('should handle offset correctly', () => { const arr = new Uint8Array(64); be32(arr, 32, BigInt('0x1234567890abcdef')); expect(bytesToHex(arr.slice(0, 32))).to.equal('0000000000000000000000000000000000000000000000000000000000000000'); expect(bytesToHex(arr.slice(32))).to.equal('0000000000000000000000000000000000000000000000001234567890abcdef'); }); it('should handle zero correctly', () => { const arr = new Uint8Array(32); be32(arr, 0, BigInt(0)); expect(bytesToHex(arr)).to.equal('0000000000000000000000000000000000000000000000000000000000000000'); }); it('should handle maximum 256-bit number', () => { const arr = new Uint8Array(32); const maxValue = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); be32(arr, 0, maxValue); expect(bytesToHex(arr)).to.equal('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); }); it('should throw error for number larger than 256 bits', () => { const arr = new Uint8Array(32); const tooLarge = BigInt('0x10000000000000000000000000000000000000000000000000000000000000000'); expect(() => be32(arr, 0, tooLarge)).to.throw(RangeError, 'integer > 256 bits'); }); }); });