Skip to content

Commit 72b2aa0

Browse files
committed
feat: getPublicKeyEd25519 tests and benchmark
1 parent a66200c commit 72b2aa0

File tree

10 files changed

+3633
-2
lines changed

10 files changed

+3633
-2
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,6 @@ nitrogen/
8989
cpp/botan_generated/
9090

9191
# Eslint
92-
.eslintcache
92+
.eslintcache
93+
94+
noble-curves-example/

example/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
},
1515
"dependencies": {
1616
"@ethereumjs/util": "^10.0.0",
17+
"@noble/curves": "^1.8.0",
1718
"@noble/hashes": "^1.8.0",
1819
"@noble/secp256k1": "^2.3.0",
1920
"react": "19.0.0",

example/src/App.tsx

Lines changed: 202 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,33 @@ import {
4848
runAllKeccak256Benchmarks,
4949
type BenchmarkResult as Keccak256BenchmarkResult,
5050
} from './benchmarks/keccak256Benchmark';
51+
import {
52+
runAllEd25519Benchmarks,
53+
type BenchmarkResult as Ed25519BenchmarkResult,
54+
} from './benchmarks/ed25519Benchmark';
55+
import {
56+
testEd25519BasicFunctionality,
57+
testEd25519PublicKeyFormat,
58+
testEd25519KnownVectors,
59+
testEd25519InputVariants,
60+
testEd25519Uint8ArrayEdgeCases,
61+
testEd25519NobleComparison,
62+
testEd25519ErrorHandling,
63+
} from './tests/ed25519Tests';
64+
import { runAllEd25519NobleExtractedTests } from './tests/ed25519NobleExtractedTests';
65+
import {
66+
verifyMultipleEd25519Vectors,
67+
type Ed25519VerificationResult,
68+
} from './tests/ed25519NobleCompatibilityTests';
5169

5270
// Define test suite configuration
5371
interface TestSuite {
5472
name: string;
55-
runner: () => TestResult[] | ValidationResult[] | VerificationResult[];
73+
runner: () =>
74+
| TestResult[]
75+
| ValidationResult[]
76+
| VerificationResult[]
77+
| Ed25519VerificationResult[];
5678
key: string;
5779
}
5880

@@ -66,6 +88,9 @@ export default function App() {
6688
verification: VerificationResult[];
6789
pubToAddress: TestResult[];
6890
keccak256: TestResult[];
91+
ed25519: TestResult[];
92+
ed25519Noble: TestResult[];
93+
ed25519Verification: Ed25519VerificationResult[];
6994
}>({
7095
basic: [],
7196
noble: [],
@@ -75,18 +100,23 @@ export default function App() {
75100
verification: [],
76101
pubToAddress: [],
77102
keccak256: [],
103+
ed25519: [],
104+
ed25519Noble: [],
105+
ed25519Verification: [],
78106
});
79107

80108
const [benchmarkResults, setBenchmarkResults] = useState<{
81109
suite: BenchmarkSuite | null;
82110
hmacSuite: HmacBenchmarkResult[] | null;
83111
pubToAddressSuite: PubToAddressBenchmarkResult[] | null;
84112
keccak256Suite: Keccak256BenchmarkResult[] | null;
113+
ed25519Suite: Ed25519BenchmarkResult[] | null;
85114
}>({
86115
suite: null,
87116
hmacSuite: null,
88117
pubToAddressSuite: null,
89118
keccak256Suite: null,
119+
ed25519Suite: null,
90120
});
91121

92122
const [isRunning, setIsRunning] = useState(false);
@@ -148,6 +178,29 @@ export default function App() {
148178
key: 'keccak256',
149179
runner: () => runAllKeccak256Tests(),
150180
},
181+
{
182+
name: 'getPublicKeyEd25519',
183+
key: 'ed25519',
184+
runner: () => [
185+
...testEd25519BasicFunctionality(),
186+
...testEd25519PublicKeyFormat(),
187+
...testEd25519KnownVectors(),
188+
...testEd25519InputVariants(),
189+
...testEd25519Uint8ArrayEdgeCases(),
190+
...testEd25519NobleComparison(),
191+
...testEd25519ErrorHandling(),
192+
],
193+
},
194+
{
195+
name: 'getPublicKeyEd25519 - converted test cases from noble/curves',
196+
key: 'ed25519Noble',
197+
runner: () => runAllEd25519NobleExtractedTests(),
198+
},
199+
{
200+
name: 'getPublicKeyEd25519 - custom noble/curves compatibility tests',
201+
key: 'ed25519Verification',
202+
runner: () => verifyMultipleEd25519Vectors(),
203+
},
151204
];
152205

153206
const clearAllResults = () => {
@@ -161,12 +214,16 @@ export default function App() {
161214
verification: [],
162215
pubToAddress: [],
163216
keccak256: [],
217+
ed25519: [],
218+
ed25519Noble: [],
219+
ed25519Verification: [],
164220
});
165221
setBenchmarkResults({
166222
suite: null,
167223
hmacSuite: null,
168224
pubToAddressSuite: null,
169225
keccak256Suite: null,
226+
ed25519Suite: null,
170227
});
171228
};
172229

@@ -217,6 +274,15 @@ export default function App() {
217274
nobleCompressed: '',
218275
},
219276
];
277+
} else if (suite.key === 'ed25519Verification') {
278+
(newResults as any)[suite.key] = [
279+
{
280+
matches: false,
281+
privateKey: '',
282+
nativePublicKey: '',
283+
noblePublicKey: '',
284+
},
285+
];
220286
} else {
221287
(newResults as any)[suite.key] = [errorResult];
222288
}
@@ -271,6 +337,9 @@ export default function App() {
271337
...testResults.verification.map((r) => ({ success: r.matches })),
272338
...testResults.pubToAddress.map((r) => ({ success: r.success })),
273339
...testResults.keccak256.map((r) => ({ success: r.success })),
340+
...testResults.ed25519.map((r) => ({ success: r.success })),
341+
...testResults.ed25519Noble.map((r) => ({ success: r.success })),
342+
...testResults.ed25519Verification.map((r) => ({ success: r.matches })),
274343
];
275344

276345
const totalTests = allResults.length;
@@ -294,6 +363,10 @@ export default function App() {
294363
passed = results.filter((r: ValidationResult) => r.success).length;
295364
} else if (key === 'verification') {
296365
passed = results.filter((r: VerificationResult) => r.matches).length;
366+
} else if (key === 'ed25519Verification') {
367+
passed = results.filter(
368+
(r: Ed25519VerificationResult) => r.matches,
369+
).length;
297370
} else if (key === 'pubToAddress') {
298371
passed = results.filter((r: TestResult) => r.success).length;
299372
} else if (key === 'keccak256') {
@@ -381,6 +454,17 @@ export default function App() {
381454
disabled={isRunning}
382455
/>
383456
</View>
457+
<View style={styles.buttonContainer}>
458+
<Button
459+
title={
460+
isRunning ? '⏳ Running...' : '🔑 Ed25519 Full Benchmark'
461+
}
462+
onPress={() =>
463+
runBenchmark('ed25519Suite', runAllEd25519Benchmarks)
464+
}
465+
disabled={isRunning}
466+
/>
467+
</View>
384468
</View>
385469
{benchmarkProgress && (
386470
<Text style={styles.progressText}>
@@ -499,6 +583,38 @@ export default function App() {
499583
</>
500584
)}
501585
</>
586+
) : suite.key === 'ed25519Verification' ? (
587+
<>
588+
<Text
589+
style={[
590+
styles.testName,
591+
result.matches ? styles.success : styles.failure,
592+
]}
593+
>
594+
{result.matches ? '✓' : '✗'} Private Key:{' '}
595+
{result.privateKey.slice(-8)}
596+
</Text>
597+
<Text style={styles.testMessage}>
598+
Native Ed25519: {result.nativePublicKey.slice(0, 20)}...
599+
</Text>
600+
<Text style={styles.testMessage}>
601+
Noble Ed25519: {result.noblePublicKey.slice(0, 20)}
602+
...
603+
</Text>
604+
{!result.matches && (
605+
<>
606+
<Text style={[styles.testMessage, styles.failure]}>
607+
❌ MISMATCH DETECTED
608+
</Text>
609+
<Text style={styles.testMessage}>
610+
Full Native: {result.nativePublicKey}
611+
</Text>
612+
<Text style={styles.testMessage}>
613+
Full Noble: {result.noblePublicKey}
614+
</Text>
615+
</>
616+
)}
617+
</>
502618
) : suite.key === 'pubToAddress' ? (
503619
<>
504620
<Text
@@ -852,6 +968,91 @@ export default function App() {
852968
)}
853969
</View>
854970
)}
971+
972+
{benchmarkResults.ed25519Suite && (
973+
<View style={styles.section}>
974+
<Text style={styles.sectionTitle}>
975+
🔑 Ed25519 Public Key Generation Benchmark Suite
976+
</Text>
977+
<View style={styles.benchmarkSummary}>
978+
<Text style={styles.benchmarkSummaryTitle}>
979+
📊 Performance Overview
980+
</Text>
981+
<Text style={styles.benchmarkSummaryText}>
982+
{benchmarkResults.ed25519Suite.length} key generation scenarios
983+
tested
984+
</Text>
985+
<Text style={styles.benchmarkSummaryText}>
986+
Average Speedup:{' '}
987+
{(
988+
benchmarkResults.ed25519Suite.reduce(
989+
(sum: number, r: any) => sum + r.comparison.speedupFactor,
990+
0,
991+
) / benchmarkResults.ed25519Suite.length
992+
).toFixed(2)}
993+
x
994+
</Text>
995+
<Text style={styles.benchmarkSummaryText}>
996+
All Faster:{' '}
997+
{benchmarkResults.ed25519Suite.every(
998+
(r: any) => r.comparison.nativeIsFaster,
999+
)
1000+
? '✅ Yes'
1001+
: '❌ No'}
1002+
</Text>
1003+
</View>
1004+
<Text style={styles.sectionSubtitle}>Individual Test Results:</Text>
1005+
{benchmarkResults.ed25519Suite.map((result: any, index: number) => {
1006+
const getTestIcon = (testName: string) => {
1007+
if (testName.includes('Random')) return '🎲';
1008+
if (testName.includes('RFC')) return '📖';
1009+
return '🔑';
1010+
};
1011+
1012+
return (
1013+
<View key={index} style={styles.benchmarkResult}>
1014+
<Text style={styles.benchmarkTitle}>
1015+
{getTestIcon(result.testName)} {result.testName}
1016+
</Text>
1017+
<View style={styles.benchmarkMetrics}>
1018+
<Text style={styles.benchmarkDetails}>
1019+
🚀 Native: {result.native.averageTime.toFixed(3)}ms avg •{' '}
1020+
{result.native.iops.toFixed(0)} ops/sec
1021+
</Text>
1022+
<Text style={styles.benchmarkDetails}>
1023+
📜 Noble: {result.javascript.averageTime.toFixed(3)}ms avg
1024+
{result.javascript.iops.toFixed(0)} ops/sec
1025+
</Text>
1026+
<Text
1027+
style={[
1028+
styles.benchmarkComparison,
1029+
result.comparison.nativeIsFaster
1030+
? styles.success
1031+
: styles.failure,
1032+
]}
1033+
>
1034+
{result.comparison.speedupFactor.toFixed(2)}x{' '}
1035+
{result.comparison.nativeIsFaster ? 'faster' : 'slower'}{' '}
1036+
{result.comparison.performanceGain.toFixed(1)}%
1037+
improvement
1038+
</Text>
1039+
<Text style={styles.benchmarkRange}>
1040+
📈 Range: {result.native.minTime.toFixed(3)}ms -{' '}
1041+
{result.native.maxTime.toFixed(3)}ms (Native) |{' '}
1042+
{result.javascript.minTime.toFixed(3)}ms -{' '}
1043+
{result.javascript.maxTime.toFixed(3)}ms (Noble)
1044+
</Text>
1045+
<Text style={styles.benchmarkStats}>
1046+
📊 Std Dev: ±{result.native.standardDeviation.toFixed(3)}
1047+
ms (Native) • ±
1048+
{result.javascript.standardDeviation.toFixed(3)}ms (Noble)
1049+
</Text>
1050+
</View>
1051+
</View>
1052+
);
1053+
})}
1054+
</View>
1055+
)}
8551056
</View>
8561057
</ScrollView>
8571058
);

0 commit comments

Comments
 (0)