Class 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(byte[], Secp256k1.EcdsaSignature, byte[]), Schnorr.verify(byte[], byte[], byte[]),
Ed25519.verify(byte[], byte[], byte[]) 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
CryptoBatch.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 Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceThe answer of an asynchronous batch. -
Method Summary
Modifier and TypeMethodDescriptionstatic byte[][]keccak256(byte[][] inputs) The Keccak-256 of each input (Ethereum's hash).static voidkeccak256(byte[] inputs, int inputLength, int count, byte[] digests) The Keccak-256 ofcountpacked inputs, laid out as [#sha256(byte[], int, int, byte[])].static voidkeccak256Async(byte[][] inputs, CryptoBatch.Callback<byte[][]> callback) [#keccak256(byte[][])] off the calling thread.static voidkeccak256Async(byte[] inputs, int inputLength, int count, byte[] digests, CryptoBatch.Callback<byte[]> callback) [#keccak256(byte[], int, int, byte[])] off the calling thread; the callback getsdigests.static byte[][]sha256(byte[][] inputs) The SHA-256 of each input.static voidsha256(byte[] inputs, int inputLength, int count, byte[] digests) The SHA-256 ofcountinputs ofinputLengthbytes each, inputiatinputLength * iofinputsand its digest written at32 * iofdigests.static voidsha256Async(byte[][] inputs, CryptoBatch.Callback<byte[][]> callback) [#sha256(byte[][])] off the calling thread.static voidsha256Async(byte[] inputs, int inputLength, int count, byte[] digests, CryptoBatch.Callback<byte[]> callback) [#sha256(byte[], int, int, byte[])] off the calling thread; the callback getsdigests.static boolean[]verifyEd25519(byte[][] messages, byte[][] signatures, byte[][] publicKeys) Ed25519, entry by entry asEd25519.verify(byte[], byte[], byte[]): each message, 64-byte signature and 32-byte public key.static voidverifyEd25519(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)].static voidverifyEd25519Async(byte[][] messages, byte[][] signatures, byte[][] publicKeys, CryptoBatch.Callback<boolean[]> callback) [#verifyEd25519(byte[][], byte[][], byte[][])] off the calling thread.static voidverifyEd25519Async(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)].static boolean[]verifySchnorr(byte[][] messages, byte[][] signatures, byte[][] publicKeys) BIP-340 Schnorr, entry by entry asSchnorr.verify(byte[], byte[], byte[]): each message, 64-byte signature and 32-byte x-only public key.static voidverifySchnorr(byte[] messages, int messageLength, byte[] signatures, byte[] publicKeys, byte[] results, int count) The packed form of [#verifySchnorr(byte[][], byte[][], byte[][])]: entryiis the message ofmessageLengthbytes atmessageLength * iofmessages, the 64-byte signature at64 * iofsignaturesand the 32-byte x-only key at32 * iofpublicKeys.static voidverifySchnorrAsync(byte[][] messages, byte[][] signatures, byte[][] publicKeys, CryptoBatch.Callback<boolean[]> callback) [#verifySchnorr(byte[][], byte[][], byte[][])] off the calling thread.static voidverifySchnorrAsync(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)].static boolean[]verifySecp256k1(byte[][] hashes, Secp256k1.EcdsaSignature[] signatures, byte[][] publicKeys) ECDSA over secp256k1, entry by entry asSecp256k1.verify(byte[], Secp256k1.EcdsaSignature, byte[]): each 32-byte hash, signature and SEC1 public key.static voidverifySecp256k1(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.static voidverifySecp256k1Async(byte[][] hashes, Secp256k1.EcdsaSignature[] signatures, byte[][] publicKeys, CryptoBatch.Callback<boolean[]> callback) [#verifySecp256k1(byte[][], Secp256k1.EcdsaSignature[], byte[][])] off the calling thread.static voidverifySecp256k1Async(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.
-
Method Details
-
verifySecp256k1
public static boolean[] verifySecp256k1(byte[][] hashes, Secp256k1.EcdsaSignature[] signatures, byte[][] publicKeys) ECDSA over secp256k1, entry by entry asSecp256k1.verify(byte[], Secp256k1.EcdsaSignature, byte[]): 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 asSchnorr.verify(byte[], byte[], byte[]): 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 asEd25519.verify(byte[], byte[], byte[]): each message, 64-byte signature and 32-byte public key. -
sha256
public static byte[][] sha256(byte[][] inputs) The SHA-256 of each input. Anullinput has anulldigest. -
keccak256
public static byte[][] keccak256(byte[][] inputs) The Keccak-256 of each input (Ethereum's hash). Anullinput has anulldigest. -
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
iis the 32-byte hash at32 * iofhashes, the 64-byte compact signature (r || s) at64 * iofsignatures, and the SEC1 public key ofpublicKeyLengthbytes (33 or 65) atpublicKeyLength * iofpublicKeys. Writes 1 (valid) or 0 to each of the firstcountbytes ofresults; 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[][])]: entryiis the message ofmessageLengthbytes atmessageLength * iofmessages, the 64-byte signature at64 * iofsignaturesand the 32-byte x-only key at32 * iofpublicKeys. Writes 1 or 0 to each of the firstcountbytes ofresults. 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 ofcountinputs ofinputLengthbytes each, inputiatinputLength * iofinputsand its digest written at32 * iofdigests. A level of a Merkle tree isinputLength64 over the level below;digestsmay then be the next level'sinputs. -
keccak256
public static void keccak256(byte[] inputs, int inputLength, int count, byte[] digests) The Keccak-256 ofcountpacked 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
[#sha256(byte[][])] off the calling thread. -
keccak256Async
[#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 getsresultsonce 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 getsdigests. -
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 getsdigests.
-