From d8b1bc691a34ecc9d7aa830cb29486e415fb3ac3 Mon Sep 17 00:00:00 2001 From: Arjun Porwal Date: Mon, 8 Dec 2025 15:49:20 +0530 Subject: [PATCH 1/4] docs: add sr25519 migration guide --- docs/util-crypto/sr25519-migration.md | 242 ++++++++++++++++++++++++++ sidebars.js | 1 + 2 files changed, 243 insertions(+) create mode 100644 docs/util-crypto/sr25519-migration.md diff --git a/docs/util-crypto/sr25519-migration.md b/docs/util-crypto/sr25519-migration.md new file mode 100644 index 000000000..48393af2d --- /dev/null +++ b/docs/util-crypto/sr25519-migration.md @@ -0,0 +1,242 @@ +# sr25519 Migration Guide + +## Overview + +Polkadot.js has migrated from WASM-based sr25519 cryptography to [`@scure/sr25519`](https://github.com/paulmillr/scure-sr25519), a pure JavaScript implementation. This change brings several benefits: + +- **No WASM initialization required** - Functions are now synchronous +- **Smaller bundle size** - Few lines of pure JS vs WASM binaries +- **Better compatibility** - Works seamlessly across all JavaScript environments +- **Audited & secure** - Multiple independent security audits by Oak Security + +## Breaking Changes + +### 1. Synchronous Operations (No More `async`/`await`) + +**Before (WASM):** +```javascript +import { cryptoWaitReady, sr25519Sign } from '@polkadot/util-crypto'; + +async function signMessage() { + // Wait for WASM to initialize + await cryptoWaitReady(); + + const signature = await sr25519Sign(message, keypair); + return signature; +} +``` + +**After (Pure JS):** +```javascript +import { sr25519Sign } from '@polkadot/util-crypto'; + +function signMessage() { + // No initialization needed - works immediately + const signature = sr25519Sign(message, keypair); + return signature; +} +``` + +### 2. No WASM Initialization + +You no longer need to call `cryptoWaitReady()` for sr25519 operations. The following patterns are now unnecessary: + +```javascript +// ❌ OLD - No longer needed +await cryptoWaitReady(); + +// ❌ OLD - No longer needed +if (isReady) { + // sr25519 operations +} +``` + +All sr25519 functions are ready to use immediately upon import. + +## Migration Checklist + +- [ ] Remove `await` from sr25519 function calls +- [ ] Remove `cryptoWaitReady()` calls if only used for sr25519 +- [ ] Remove `async` from functions that only contained sr25519 operations +- [ ] Update error handling (no more promise rejections) +- [ ] Test synchronous execution flow in your application + +## API Changes + +### Key Generation + +```javascript +// ✅ NEW - Synchronous +import { sr25519PairFromSeed } from '@polkadot/util-crypto'; + +const seed = new Uint8Array(32); // Your seed +const keypair = sr25519PairFromSeed(seed); +``` + +### Signing + +```javascript +// ✅ NEW - Synchronous +import { sr25519Sign } from '@polkadot/util-crypto'; + +const message = new Uint8Array([1, 2, 3, 4]); +const signature = sr25519Sign(message, keypair); +``` + +### Verification + +```javascript +// ✅ NEW - Synchronous +import { sr25519Verify } from '@polkadot/util-crypto'; + +const isValid = sr25519Verify(message, signature, publicKey); +``` + +### Key Derivation + +```javascript +// ✅ NEW - Synchronous +import { sr25519DeriveHard, sr25519DeriveSoft } from '@polkadot/util-crypto'; + +// Hard derivation +const derived = sr25519DeriveHard(keypair, chainCode); + +// Soft derivation +const derivedSoft = sr25519DeriveSoft(keypair, chainCode); +``` + +### VRF Operations + +```javascript +// ✅ NEW - Synchronous +import { sr25519VrfSign, sr25519VrfVerify } from '@polkadot/util-crypto'; + +const vrfSignature = sr25519VrfSign(message, keypair, context); +const vrfValid = sr25519VrfVerify(message, vrfSignature, publicKey, context); +``` + +## Performance Considerations + +### Bundle Size +- **WASM implementation**: ~100KB+ (WASM binary + JS wrapper) +- **Pure JS implementation**: ~15KB minified + +### Execution Speed +- Pure JS may be slightly slower than WASM for bulk operations +- For typical single-signature operations, the difference is negligible +- No initialization overhead (WASM required loading and compilation) + +### When to Use +The pure JS implementation is ideal for: +- Browser applications (smaller bundles, faster load times) +- Server-side applications (no WASM compilation overhead) +- Mobile applications (better compatibility) +- Applications requiring immediate cryptographic operations + +## Security & Audits + +The `@scure/sr25519` library has undergone multiple independent security audits. All audit reports are publicly available: +- [Oak Security Audit Reports](https://github.com/oak-security/audit-reports/tree/main/Polkadot) + +The library was funded by the Polkadot Treasury and developed specifically for the Polkadot ecosystem. + +## Node.js Version Requirements + +- **Current**: Node.js v18+ (using `@scure/sr25519` v0.2.x) +- **Future**: Node.js v20+ recommended (for ESM-only v0.3.x updates) + +## Common Patterns + +### Before & After Examples + +#### Example 1: Creating and Signing with a Keypair + +```javascript +// ❌ OLD +import { cryptoWaitReady, sr25519PairFromSeed } from '@polkadot/util-crypto'; + +async function createAndSign(seed, message) { + await cryptoWaitReady(); + const pair = sr25519PairFromSeed(seed); + return pair.sign(message); +} + +// ✅ NEW +import { sr25519PairFromSeed } from '@polkadot/util-crypto'; + +function createAndSign(seed, message) { + const pair = sr25519PairFromSeed(seed); + return pair.sign(message); +} +``` + +#### Example 2: Batch Verification + +```javascript +// ❌ OLD +async function verifyMultiple(signatures) { + await cryptoWaitReady(); + return signatures.map(({ msg, sig, pub }) => + sr25519Verify(msg, sig, pub) + ); +} + +// ✅ NEW +function verifyMultiple(signatures) { + return signatures.map(({ msg, sig, pub }) => + sr25519Verify(msg, sig, pub) + ); +} +``` + +#### Example 3: Initialization in React + +```javascript +// ❌ OLD +function MyComponent() { + const [ready, setReady] = useState(false); + + useEffect(() => { + cryptoWaitReady().then(() => setReady(true)); + }, []); + + if (!ready) return ; + return ; +} + +// ✅ NEW +function MyComponent() { + // No initialization needed - just use it! + return ; +} +``` + +## Troubleshooting + +### "Function is not async but I'm using await" +Remove the `await` keyword - sr25519 functions are now synchronous. + +### "cryptoWaitReady is not defined" +Remove calls to `cryptoWaitReady()` - it's no longer needed for sr25519 operations. + +### "Performance seems slower" +For bulk operations, consider batching or using Web Workers. For typical use cases, performance should be comparable or better due to no initialization overhead. + +### "TypeScript errors about async/await" +Update your function signatures to remove `async` and `Promise` return types for sr25519 operations. + +## Additional Resources + +- [`@scure/sr25519` GitHub Repository](https://github.com/paulmillr/scure-sr25519) +- [Polkadot.js Documentation](https://polkadot.js.org/docs/) +- [Original PR Discussion](https://github.com/polkadot-js/common/pull/1971) +- [Oak Security Audit Reports](https://github.com/oak-security/audit-reports/tree/main/Polkadot) + +## Questions or Issues? + +If you encounter any issues during migration: +1. Check this guide for common patterns +2. Review the [@polkadot-js/common GitHub issues](https://github.com/polkadot-js/common/issues) +3. Open an issue on the [@polkadot-js/common repository](https://github.com/polkadot-js/common/issues/new) + +--- \ No newline at end of file diff --git a/sidebars.js b/sidebars.js index cdbbabc02..9601887c8 100644 --- a/sidebars.js +++ b/sidebars.js @@ -127,6 +127,7 @@ module.exports = { ], 'Crypto Utilities': [ 'util-crypto/intro', + 'util-crypto/sr25519-migration', { Examples: [ 'util-crypto/examples/intro', From 9492dc0e476b16756de04f44867b193574686521 Mon Sep 17 00:00:00 2001 From: Arjun Porwal Date: Mon, 8 Dec 2025 18:25:14 +0530 Subject: [PATCH 2/4] chore: got rid of emojis --- docs/util-crypto/sr25519-migration.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/util-crypto/sr25519-migration.md b/docs/util-crypto/sr25519-migration.md index 48393af2d..9299b571f 100644 --- a/docs/util-crypto/sr25519-migration.md +++ b/docs/util-crypto/sr25519-migration.md @@ -42,10 +42,10 @@ function signMessage() { You no longer need to call `cryptoWaitReady()` for sr25519 operations. The following patterns are now unnecessary: ```javascript -// ❌ OLD - No longer needed +// OLD - No longer needed await cryptoWaitReady(); -// ❌ OLD - No longer needed +// OLD - No longer needed if (isReady) { // sr25519 operations } @@ -66,7 +66,7 @@ All sr25519 functions are ready to use immediately upon import. ### Key Generation ```javascript -// ✅ NEW - Synchronous +// NEW - Synchronous import { sr25519PairFromSeed } from '@polkadot/util-crypto'; const seed = new Uint8Array(32); // Your seed @@ -76,7 +76,7 @@ const keypair = sr25519PairFromSeed(seed); ### Signing ```javascript -// ✅ NEW - Synchronous +// NEW - Synchronous import { sr25519Sign } from '@polkadot/util-crypto'; const message = new Uint8Array([1, 2, 3, 4]); @@ -86,7 +86,7 @@ const signature = sr25519Sign(message, keypair); ### Verification ```javascript -// ✅ NEW - Synchronous +// NEW - Synchronous import { sr25519Verify } from '@polkadot/util-crypto'; const isValid = sr25519Verify(message, signature, publicKey); @@ -95,7 +95,7 @@ const isValid = sr25519Verify(message, signature, publicKey); ### Key Derivation ```javascript -// ✅ NEW - Synchronous +// NEW - Synchronous import { sr25519DeriveHard, sr25519DeriveSoft } from '@polkadot/util-crypto'; // Hard derivation @@ -108,7 +108,7 @@ const derivedSoft = sr25519DeriveSoft(keypair, chainCode); ### VRF Operations ```javascript -// ✅ NEW - Synchronous +// NEW - Synchronous import { sr25519VrfSign, sr25519VrfVerify } from '@polkadot/util-crypto'; const vrfSignature = sr25519VrfSign(message, keypair, context); @@ -152,7 +152,7 @@ The library was funded by the Polkadot Treasury and developed specifically for t #### Example 1: Creating and Signing with a Keypair ```javascript -// ❌ OLD +// OLD import { cryptoWaitReady, sr25519PairFromSeed } from '@polkadot/util-crypto'; async function createAndSign(seed, message) { @@ -161,7 +161,7 @@ async function createAndSign(seed, message) { return pair.sign(message); } -// ✅ NEW +// NEW import { sr25519PairFromSeed } from '@polkadot/util-crypto'; function createAndSign(seed, message) { @@ -173,7 +173,7 @@ function createAndSign(seed, message) { #### Example 2: Batch Verification ```javascript -// ❌ OLD +// OLD async function verifyMultiple(signatures) { await cryptoWaitReady(); return signatures.map(({ msg, sig, pub }) => @@ -181,7 +181,7 @@ async function verifyMultiple(signatures) { ); } -// ✅ NEW +// NEW function verifyMultiple(signatures) { return signatures.map(({ msg, sig, pub }) => sr25519Verify(msg, sig, pub) @@ -192,7 +192,7 @@ function verifyMultiple(signatures) { #### Example 3: Initialization in React ```javascript -// ❌ OLD +// OLD function MyComponent() { const [ready, setReady] = useState(false); @@ -204,7 +204,7 @@ function MyComponent() { return ; } -// ✅ NEW +// NEW function MyComponent() { // No initialization needed - just use it! return ; From 66ad06edd574db5d2448730ea8213f0dbe217ca4 Mon Sep 17 00:00:00 2001 From: Arjun Porwal Date: Tue, 9 Dec 2025 13:05:52 +0530 Subject: [PATCH 3/4] chore: added v1.x --- docs/util-crypto/sr25519-migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/util-crypto/sr25519-migration.md b/docs/util-crypto/sr25519-migration.md index 9299b571f..b7f472177 100644 --- a/docs/util-crypto/sr25519-migration.md +++ b/docs/util-crypto/sr25519-migration.md @@ -143,7 +143,7 @@ The library was funded by the Polkadot Treasury and developed specifically for t ## Node.js Version Requirements - **Current**: Node.js v18+ (using `@scure/sr25519` v0.2.x) -- **Future**: Node.js v20+ recommended (for ESM-only v0.3.x updates) +- **Future**: Node.js v20+ recommended (for ESM-only v0.3.x/v1.x updates) ## Common Patterns From f55ca02b8491c9af0a227e68b9be50a3992895d0 Mon Sep 17 00:00:00 2001 From: Arjun Porwal Date: Tue, 9 Dec 2025 13:11:27 +0530 Subject: [PATCH 4/4] feat: add note about optional cryptoWaitReady usage --- docs/util-crypto/sr25519-migration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/util-crypto/sr25519-migration.md b/docs/util-crypto/sr25519-migration.md index b7f472177..74b8f426f 100644 --- a/docs/util-crypto/sr25519-migration.md +++ b/docs/util-crypto/sr25519-migration.md @@ -133,6 +133,8 @@ The pure JS implementation is ideal for: - Mobile applications (better compatibility) - Applications requiring immediate cryptographic operations +> You can optionally call `cryptoWaitReady()` during initialization to ensure async crypto imports are fully available before use. This works safely alongside synchronous usage and won’t interfere with other crypto imports, which can be useful in projects that rely on multiple crypto libraries or shared initialization logic. + ## Security & Audits The `@scure/sr25519` library has undergone multiple independent security audits. All audit reports are publicly available: