Client and backend. This class is shared: the same code is compiled into your app and into your server, so everything on this page works in both.

public final class CryptoBatch

  1. Object
  2. CryptoBatch

Many signature verifications or hashes in one call: the deposits of a block an exchange scans, the transactions an indexer checks, the leaves of a Merkle tree.

Where the platform has native kernels the whole batch crosses into native code once and is spread over every CPU core, so a batch of thousands runs several times faster than the same calls one at a time. Elsewhere it is the same loop over Secp256k1.verify, Schnorr.verify, Ed25519.verify or Hash that a caller would write.

Every entry gets exactly the answer the single call gives it; nothing here uses a batch equation that could accept a signature a single verify rejects. A malformed entry – a null, a key that does not parse, a wrong length – is simply invalid, so one bad entry never aborts the rest.

Every method has an asynchronous form, named with Async and taking a Callback, which runs the same batch off the calling thread. In the app the callback runs on the EDT, so a screen can start a batch and show its result without blocking; in a backend it runs on the thread that did the work. In a browser the asynchronous forms are the ones to use: there a large batch goes to the GPU through WebGPU, which answers only asynchronously, and the synchronous form holds its thread for that long. The arguments are checked before the call returns, so a malformed batch throws right away rather than reaching the callback. The batch reads the arrays it was given, not a copy, so they belong to it until the callback runs: changing one before then changes the entries being verified. The callback runs exactly once, with the result or with whatever was thrown, an Error included.

Nested types

interface CryptoBatch.CallbackThe answer of an asynchronous batch.

Methods

public static boolean[] verifySecp256k1(byte[][] hashes, Secp256k1.EcdsaSignature[] signatures, byte[][] publicKeys)ECDSA over secp256k1, entry by entry as Secp256k1.verify: each 32-byte hash, signature and SEC1 public key.
public static boolean[] verifySchnorr(byte[][] messages, byte[][] signatures, byte[][] publicKeys)BIP-340 Schnorr, entry by entry as Schnorr.verify: each message, 64-byte signature and 32-byte x-only public key.
public static boolean[] verifyEd25519(byte[][] messages, byte[][] signatures, byte[][] publicKeys)Ed25519, entry by entry as Ed25519.verify: each message, 64-byte signature and 32-byte public key.
public static byte[][] sha256(byte[][] inputs)The SHA-256 of each input.
public static byte[][] keccak256(byte[][] inputs)The Keccak-256 of each input (Ethereum’s hash).
public static void verifySecp256k1(byte[] hashes, byte[] signatures, byte[] publicKeys, int publicKeyLength, byte[] results, int count)The packed form of [#verifySecp256k1(byte[][], Secp256k1.EcdsaSignature[], byte[][])], for batches large enough that an object per entry matters.
public static void verifySchnorr(byte[] messages, int messageLength, byte[] signatures, byte[] publicKeys, byte[] results, int count)The packed form of [#verifySchnorr(byte[][], byte[][], byte[][])]: entry i is the message of messageLength bytes at messageLength * i of messages, the 64-byte signature at 64 * i of signatures and the 32-byte x-only key at 32 * i of publicKeys.
public static void verifyEd25519(byte[] messages, int messageLength, byte[] signatures, byte[] publicKeys, byte[] results, int count)The packed form of [#verifyEd25519(byte[][], byte[][], byte[][])], laid out as [#verifySchnorr(byte[], int, byte[], byte[], byte[], int)].
public static void sha256(byte[] inputs, int inputLength, int count, byte[] digests)The SHA-256 of count inputs of inputLength bytes each, input i at inputLength * i of inputs and its digest written at 32 * i of digests.
public static void keccak256(byte[] inputs, int inputLength, int count, byte[] digests)The Keccak-256 of count packed inputs, laid out as [#sha256(byte[], int, int, byte[])].
public static void verifySecp256k1Async(byte[][] hashes, Secp256k1.EcdsaSignature[] signatures, byte[][] publicKeys, CryptoBatch.Callback<boolean[]> callback)[#verifySecp256k1(byte[][], Secp256k1.EcdsaSignature[], byte[][])] off the calling thread.
public static void verifySchnorrAsync(byte[][] messages, byte[][] signatures, byte[][] publicKeys, CryptoBatch.Callback<boolean[]> callback)[#verifySchnorr(byte[][], byte[][], byte[][])] off the calling thread.
public static void verifyEd25519Async(byte[][] messages, byte[][] signatures, byte[][] publicKeys, CryptoBatch.Callback<boolean[]> callback)[#verifyEd25519(byte[][], byte[][], byte[][])] off the calling thread.
public static void sha256Async(byte[][] inputs, CryptoBatch.Callback<byte[][]> callback)[#sha256(byte[][])] off the calling thread.
public static void keccak256Async(byte[][] inputs, CryptoBatch.Callback<byte[][]> callback)[#keccak256(byte[][])] off the calling thread.
public static void verifySecp256k1Async(byte[] hashes, byte[] signatures, byte[] publicKeys, int publicKeyLength, byte[] results, int count, CryptoBatch.Callback<byte[]> callback)[#verifySecp256k1(byte[], byte[], byte[], int, byte[], int)] off the calling thread.
public static void verifySchnorrAsync(byte[] messages, int messageLength, byte[] signatures, byte[] publicKeys, byte[] results, int count, CryptoBatch.Callback<byte[]> callback)[#verifySchnorr(byte[], int, byte[], byte[], byte[], int)] off the calling thread, as [#verifySecp256k1Async(byte[], byte[], byte[], int, byte[], int, Callback)].
public static void verifyEd25519Async(byte[] messages, int messageLength, byte[] signatures, byte[] publicKeys, byte[] results, int count, CryptoBatch.Callback<byte[]> callback)[#verifyEd25519(byte[], int, byte[], byte[], byte[], int)] off the calling thread, as [#verifySecp256k1Async(byte[], byte[], byte[], int, byte[], int, Callback)].
public static void sha256Async(byte[] inputs, int inputLength, int count, byte[] digests, CryptoBatch.Callback<byte[]> callback)[#sha256(byte[], int, int, byte[])] off the calling thread; the callback gets digests.
public static void keccak256Async(byte[] inputs, int inputLength, int count, byte[] digests, CryptoBatch.Callback<byte[]> callback)[#keccak256(byte[], int, int, byte[])] off the calling thread; the callback gets digests.

Inherited methods

Method details

verifySecp256k1

public static boolean[] verifySecp256k1(byte[][] hashes, Secp256k1.EcdsaSignature[] signatures, byte[][] publicKeys)
ECDSA over secp256k1, entry by entry as Secp256k1.verify: each 32-byte hash, signature and SEC1 public key.

verifySchnorr

public static boolean[] verifySchnorr(byte[][] messages, byte[][] signatures, byte[][] publicKeys)
BIP-340 Schnorr, entry by entry as Schnorr.verify: each message, 64-byte signature and 32-byte x-only public key.

verifyEd25519

public static boolean[] verifyEd25519(byte[][] messages, byte[][] signatures, byte[][] publicKeys)
Ed25519, entry by entry as Ed25519.verify: each message, 64-byte signature and 32-byte public key.

sha256

public static byte[][] sha256(byte[][] inputs)
The SHA-256 of each input. A null input has a null digest.

keccak256

public static byte[][] keccak256(byte[][] inputs)
The Keccak-256 of each input (Ethereum’s hash). A null input has a null digest.

verifySecp256k1

public static void verifySecp256k1(byte[] hashes, byte[] signatures, byte[] publicKeys, int publicKeyLength, byte[] results, int count)

The packed form of [#verifySecp256k1(byte[][], Secp256k1.EcdsaSignature[], byte[][])], for batches large enough that an object per entry matters. Entry i is the 32-byte hash at 32 * i of hashes, the 64-byte compact signature (r || s) at 64 * i of signatures, and the SEC1 public key of publicKeyLength bytes (33 or 65) at publicKeyLength * i of publicKeys. Writes 1 (valid) or 0 to each of the first count bytes of results; a malformed entry is 0.

On a native target the kernels read and write these arrays where they are, without copying them, so a pipeline that fills them in place pays nothing per entry outside the verification itself. Allocating them with Simd.get().allocByte(int) in an app aligns them for the vector units and the GPU.

verifySchnorr

public static void verifySchnorr(byte[] messages, int messageLength, byte[] signatures, byte[] publicKeys, byte[] results, int count)
The packed form of [#verifySchnorr(byte[][], byte[][], byte[][])]: entry i is the message of messageLength bytes at messageLength * i of messages, the 64-byte signature at 64 * i of signatures and the 32-byte x-only key at 32 * i of publicKeys. Writes 1 or 0 to each of the first count bytes of results. See [#verifySecp256k1(byte[], byte[], byte[], int, byte[], int)] on allocating the arrays.

verifyEd25519

public static void verifyEd25519(byte[] messages, int messageLength, byte[] signatures, byte[] publicKeys, byte[] results, int count)
The packed form of [#verifyEd25519(byte[][], byte[][], byte[][])], laid out as [#verifySchnorr(byte[], int, byte[], byte[], byte[], int)].

sha256

public static void sha256(byte[] inputs, int inputLength, int count, byte[] digests)
The SHA-256 of count inputs of inputLength bytes each, input i at inputLength * i of inputs and its digest written at 32 * i of digests. A level of a Merkle tree is inputLength 64 over the level below; digests may then be the next level’s inputs.

keccak256

public static void keccak256(byte[] inputs, int inputLength, int count, byte[] digests)
The Keccak-256 of count packed inputs, laid out as [#sha256(byte[], int, int, byte[])].

verifySecp256k1Async

public static void verifySecp256k1Async(byte[][] hashes, Secp256k1.EcdsaSignature[] signatures, byte[][] publicKeys, CryptoBatch.Callback<boolean[]> callback)
[#verifySecp256k1(byte[][], Secp256k1.EcdsaSignature[], byte[][])] off the calling thread.

verifySchnorrAsync

public static void verifySchnorrAsync(byte[][] messages, byte[][] signatures, byte[][] publicKeys, CryptoBatch.Callback<boolean[]> callback)
[#verifySchnorr(byte[][], byte[][], byte[][])] off the calling thread.

verifyEd25519Async

public static void verifyEd25519Async(byte[][] messages, byte[][] signatures, byte[][] publicKeys, CryptoBatch.Callback<boolean[]> callback)
[#verifyEd25519(byte[][], byte[][], byte[][])] off the calling thread.

sha256Async

public static void sha256Async(byte[][] inputs, CryptoBatch.Callback<byte[][]> callback)
[#sha256(byte[][])] off the calling thread.

keccak256Async

public static void keccak256Async(byte[][] inputs, CryptoBatch.Callback<byte[][]> callback)
[#keccak256(byte[][])] off the calling thread.

verifySecp256k1Async

public static void verifySecp256k1Async(byte[] hashes, byte[] signatures, byte[] publicKeys, int publicKeyLength, byte[] results, int count, CryptoBatch.Callback<byte[]> callback)
[#verifySecp256k1(byte[], byte[], byte[], int, byte[], int)] off the calling thread. The callback gets results once every entry is written; until then the arrays belong to the batch and must not be changed.

verifySchnorrAsync

public static void verifySchnorrAsync(byte[] messages, int messageLength, byte[] signatures, byte[] publicKeys, byte[] results, int count, CryptoBatch.Callback<byte[]> callback)
[#verifySchnorr(byte[], int, byte[], byte[], byte[], int)] off the calling thread, as [#verifySecp256k1Async(byte[], byte[], byte[], int, byte[], int, Callback)].

verifyEd25519Async

public static void verifyEd25519Async(byte[] messages, int messageLength, byte[] signatures, byte[] publicKeys, byte[] results, int count, CryptoBatch.Callback<byte[]> callback)
[#verifyEd25519(byte[], int, byte[], byte[], byte[], int)] off the calling thread, as [#verifySecp256k1Async(byte[], byte[], byte[], int, byte[], int, Callback)].

sha256Async

public static void sha256Async(byte[] inputs, int inputLength, int count, byte[] digests, CryptoBatch.Callback<byte[]> callback)
[#sha256(byte[], int, int, byte[])] off the calling thread; the callback gets digests.

keccak256Async

public static void keccak256Async(byte[] inputs, int inputLength, int count, byte[] digests, CryptoBatch.Callback<byte[]> callback)
[#keccak256(byte[], int, int, byte[])] off the calling thread; the callback gets digests.