Skip to content

Conversation

@dynst
Copy link
Contributor

@dynst dynst commented Jul 20, 2025

This removes a WebAssembly dependency and a huge chunk of bundle size https://bundlephobia.com/package/@cosmjs/[email protected]

(The other, even more huge chunk is cosmos/cosmjs-types#98)

Closes #584
Closes #907
Closes #964
Closes #1031
Closes #1478
Closes #1585

Related: #1479 #1796

Technically, now that there's no longer a quirky requirement to await sodium.ready at the start of every function, asynchronous methods could be made synchronous now after this PR.

Considered but rejected a faster alternative to @noble/hashes Argon2id At least as long as Node 20 is supported, looks like hash-wasm is needed https://bundlephobia.com/package/[email protected]

But hopefully Argon2 just gets standardized in Web Crypto someday and then implemented by Node.js. https://twiss.github.io/webcrypto-modern-algos/#argon2

@dynst dynst force-pushed the desalinate branch 9 times, most recently from db7bc41 to 28c2583 Compare July 21, 2025 16:45
@dynst
Copy link
Contributor Author

dynst commented Jul 22, 2025

This conflicts with #1720 but let's get that one merged first.

@dynst dynst force-pushed the desalinate branch 3 times, most recently from 033cdf5 to c4da581 Compare July 23, 2025 15:50
@dynst
Copy link
Contributor Author

dynst commented Aug 7, 2025

This seems like really low-hanging fruit for a massive reduction in bundle size, is it not gonna make it into 0.35?

@webmaster128
Copy link
Member

Looks straight forward at first glance. However, I would be very surprised if the pure-JS implementation of Argon2 is as fast as the WebAssembly one. So this PR has the potential to hit existing users hard. Which then leads to the questions: who uses CosmJS pro private key encryption at all? Should we remove that functionality alltogether?

@dynst
Copy link
Contributor Author

dynst commented Aug 7, 2025

I thought if it was going to be removed it already would've been.

Releasing a slower version could make for a good scream test. Maybe mark all the types with @deprecated for one release to see if anyone complains.

https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#deprecated

Or just switch to hash-wasm instead of libsodium or noble cryptography for a fast but much smaller Argon2id implementation.

@webmaster128
Copy link
Member

Releasing a slower version could make for a good scream test.

Agreed. I would like to release a 0.36.0 tomorrow with ONLY this change in it. Then users can go back to 0.35.0 without a problem.

Could you update this PR to latest main?

Copy link
Member

@webmaster128 webmaster128 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@dynst dynst force-pushed the desalinate branch 3 times, most recently from 86d382d to aabdc79 Compare August 13, 2025 19:48
@dynst
Copy link
Contributor Author

dynst commented Aug 13, 2025

/**
* A KDF configuration that is not very strong but can be used on the main thread.
* It takes about 1 second in Node.js 16.0.0 and should have similar runtimes in other modern Wasm hosts.
*/
const basicPasswordHashingOptions: KdfConfiguration = {
algorithm: "argon2id",
params: {
outputLength: 32,
opsLimit: 24,
memLimitKib: 12 * 1024,
},
};

The basic parameters run so slowly the unit tests fail to finish in 15s. Or 60s. At least when running on Node.js 20.

https://github.com/cosmos/cosmjs/actions/runs/16947888017/job/48033364456

[@cosmjs/amino]: **************************************************
[@cosmjs/amino]: *                    Failures                    *
[@cosmjs/amino]: **************************************************
[@cosmjs/amino]: 
[@cosmjs/amino]: 1) Secp256k1HdWallet deserialize can restore
[@cosmjs/amino]:   - Error: Timeout - Async function did not complete within 15000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)
...
[@cosmjs/amino]: 2) Secp256k1HdWallet deserialize can restore multiple accounts
[@cosmjs/amino]:   - Error: Timeout - Async function did not complete within 15000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)
[@cosmjs/amino]:     8.3 deserialize
[@cosmjs/amino]:       ✓ can restore (1 min 5 secs)
[@cosmjs/amino]:       ✓ can restore multiple accounts (1 min 5 secs)

But 22 seems to have new optimizations. The result for Node 22 says:

https://github.com/cosmos/cosmjs/actions/runs/16947888017/job/48033364449

[@cosmjs/amino]:     8.3 deserialize
[@cosmjs/amino]:       ✓ can restore (10 secs)
[@cosmjs/amino]:       ✓ can restore multiple accounts (10 secs)

So just to keep CI happy - until Node.js 20 is dropped - maybe hash-wasm is necessary for now. It makes the unit test finish in less than a second.

The absolutely huge performance improvement for this low-level math code in 22 might be related to https://v8.dev/blog/maglev

https://nodejs.org/en/blog/announcements/v22-release-announce

If you merge this, just make sure and do a branch-merge and not a squashed commit, so it's easy to revert the last few commits separately later.

@dynst dynst force-pushed the desalinate branch 3 times, most recently from 9be002c to c97b703 Compare August 14, 2025 00:25
dynst added 3 commits August 14, 2025 00:54
This should make the deserialize 'can restore multiple accounts' unit test
take about 12s, approximating pure JS performance on node 22.
@dynst dynst force-pushed the desalinate branch 3 times, most recently from a0e779d to 7b65103 Compare August 14, 2025 01:25

// Emulate a slower implementation. The fast WASM code may get removed.
// This approximates the speed of using a pure JS implementation (@noble/hashes) in Node 22.
const screamTest = new Promise((resolve) => setTimeout(resolve, options.opsLimit * 250));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💅 we can use sleep from @cosmjs/utils which does exactly that but is a bit more readable

@webmaster128 webmaster128 merged commit 39e712a into cosmos:main Aug 14, 2025
31 of 37 checks passed
@dynst dynst mentioned this pull request Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants