Note, bitcoin-ts was renamed to Libauth in June 2020.

Just released: WebAssembly version of Secp256k1 (10x faster than Javascript)

Bitcoin, Bitcoin Cash, and most other cryptocurrencies use the Elliptic Curve Digital Signature Algorithm (ECDSA) to authenticate transactions. ECDSA can be used with a number of different elliptic curves, and Bitcoin’s creator chose the Koblitz curve Secp256k1 for Bitcoin’s digital signature system.

Secp256k1 is used by most cryptocurrency software

Most software packages which interact with these systems require Secp256k1 support. Mining software must be able to validate that transactions are properly signed before being included in the blockchain. Cryptocurrency wallets must be able to both verify incoming transactions and sign transactions to spend funds.

Many of the most popular cryptocurrency wallets and services are written in JavaScript. For these applications, Secp256k1 signing and validation can be complicated to package, use, and audit – often requiring different build and code paths for the browsers than those required for Node.js – and relatively slow (especially in browser applications).

Get the library on GitHub or NPM

A WebAssembly version of libsecp256k1 is now available on GitHub and via the Node.js package manager, NPM:

npm install --save bitcoin-ts

The API is purely-functional, fully-typed and documented with TypeScript, and accepts and returns native ES2015 typed arrays. Here’s a short example of Low-S signature verification using the library:

The library is written in TypeScript and documented inline, so capable editors will show documentation as you type:

To take advantage of the built-in documentation, try this example project in an editor with good TypeScript support, like VS Code.

For more usage information, review the code, the tests, or check out the Secp256k1 Interface in the TypeDocs.

Thoroughly tested against existing implementations

Along with standard test vectors and 100% code coverage, the library uses property-based testing to randomly generate thousands of test cases each run, including comparisons of the results against results from two other popular libraries, elliptic and secp256k1-node.

The generated WebAssembly binary is also auditable and deterministic – you can rebuild it easily yourself and verify that the NPM-distributed version is correct. Simply clone the GitHub repo, install the dependencies, and run yarn compile:wasm.

The binary is already fairly optimized (at least the low-hanging fruit), but if you’re good at optimizing WebAssembly modules, please send a pull request!

10x better performance than JavaScript, comparable to Node.js native bindings

The project includes benchmarks against both elliptic and secp256k1-node. Below are the latest performance metrics.

Benchmarks run against 3 libraries: elliptic (the JavaScript implementation), secp256k1-node (a Node.js-only interface to the C library), and bitcoin-ts, the WebAssembly implementation.

As you can see the WebAssembly version, bitcoin-ts, is around 10x faster than elliptic, the fastest JavaScript implementation, and only about 3x slower than secp256k1-node, the Node.js-only bindings to the C library.

Browser status: use it today 🥇

With a 10x performance increase, this may already be a very promising option for non-Node.js applications like wallet apps (Copay, BitPay, Blockchain.info, Bitcoin.com Wallet, Jaxx, and Exodus, to name a few).

One notable difference is code size. While the JavaScript implementation weighs in at 37KB (gzipped), the WebAssembly version is 102 KB (gzipped).

On the surface, a 3x larger size may appear to be a downside for bitcoin-ts, but it’s important to remember the bottleneck we’re usually concerned about when we consider the size of JavaScript libraries: parse and compile time. On this front, WebAssembly is significantly better: parse and compile time is orders of magnitude faster for WebAssembly than JavaScript. So despite the size increase, time-to-interactive is actually faster.

Node.js status: comparable performance, instant install ⚡

Though currently slower than the Node.js-only bindings, for Node.js applications where Secp256k1 performance isn’t a bottleneck, this library might already be preferable since it doesn’t require any native code compilation. The binary is completely portable between operating systems, and the install is nearly instant. For many applications (like in continuous integration tasks) this will already improve performance.

And it’s getting much faster 🚀

Finally, it’s important to note that WebAssembly is relatively new, and it’s still getting faster. WebAssembly only began shipping in all major browsers in November of 2017, and browsers have managed to optimize WebAssembly performance in almost every version they’ve shipped.

As WebAssembly matures, we can expect performance of this implementation to approach that of traditionally-compiled low-level software. (And according to some estimates, exceed it.)

Future plans for bitcoin-ts

Next up, bitcoin-ts will be building and exposing WebAssembly versions of other cryptographic primitives used in Bitcoin software — SHA-1, SHA-256, SHA-512, RIPEMD-160, and maybe others.

Though work will be ongoing, the library is production-ready, and will be following semantic versioning to keep already-available functionality stable. (Current version: 1.0.3)

If you’d like to support the project, please star bitcoin-ts on GitHub. If you appreciated this post, please share it so others can find it. Thanks for reading!

Next Post — Bitcoin Hashing Functions:

Just released: SHA-256, SHA-512, SHA-1, and RIPEMD-160 using WebAssembly
TL;DR: up to 20x better performance than JavaScript, and up to 4x faster than Node.js native bindings for small inputs…