Skip to content

Commit dcca904

Browse files
wip: refactor the refactor (#50)
* add blst/ to .gitignore * fix test * feat: remove sig_groupcheck * fix(testSets): SECRET_KEY_LENGTH -> SECRET_KEY_SIZE * fix(index): remove missing verify.js * rebirth * chore: a bit more restructuring on zig * more updates * feat: implement verifyMultipleAggregateSignatures * remove redundant log * chore: simplify signature and pk size consts * update aggregateWithRandomness with writing pks and sigs * simple test for AggregateSignature * revert some changes * fix(sig): fix fromBytes * update bindings * fix(verifyMultipleAggSigs): fix writers for verifyMultipleAggregateSignatures * uncomment tests * missing *Signature * chore(signature): remove unused sigValidate * fix(signature.ts): do fromBytes first then validate * fix test * fix randomness * fix: uncomment aggregateVerify test * chore: simplify naming for signature length constants * remove unused code * add writeSignatures * more test fixes * test(pk): add test for aggregatePublicKeys * define and use MAX_AGGREGATE_PER_JOB * use pointers to PublicKey in aggregatePublicKey * fix length for aggregate signatures * remove redundant print * AggregateSignature: fix rands input for aggregateWithRandomness * fix scratch for aggsig and aggpk * remove comment * uncomment more checks * chore: remove redundant SignatureSet * fix rands input to aggregateWithRandomness * fix stuff related to rands * fixes * remove redundant c abi code; mostly unused stuff * update README * chore(error): remove redundant error definitions * chore(aggPk): cleanup AggregatePublicKey.zig * small correciton * more minor changes to aggPk * chore(aggSig): doc comment and tidy up * add dst as a const * fix link for DST * doc comments for pairing.zig * finish doc comments * fix comment * remove comment * remove unnecessary import
1 parent a53ee89 commit dcca904

39 files changed

+1537
-1460
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
zig-out/
22
.zig-cache/
33
bun/node_modules/
4-
bun/benchmark_data/
4+
bun/benchmark_data/
5+
blst/

README.md

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,45 @@
11
# blst-z
2-
Zig wrapper for [supranational/blst](https://github.com/supranational/blst) native bindings, a highly performant BLS12-381 signature library.
2+
Zig bindings for [supranational's blst](https://github.com/supranational/blst) native bindings, a highly performant BLS12-381 signature library.
3+
4+
This set of bindings only support the `min_pk` variant.
35

46
## Installation
5-
- clone blst to root: `git clone --recurse-submodules https://github.com/supranational/blst.git`
6-
- `zig build test`
7+
8+
First, clone [blst](https://github.com/supranational/blst.git) to root:
9+
10+
```sh
11+
git clone --recurse-submodules https://github.com/supranational/blst.git
12+
```
13+
14+
Run zig tests:
15+
16+
```sh
17+
zig build test
18+
```
19+
20+
Install and generate bun bindings:
21+
22+
```console
23+
cd bun && bun install && bun run build && bun generate
24+
```
25+
26+
Run bun tests:
27+
28+
```sh
29+
cd bun && bun test
30+
```
31+
32+
Run bun benchmarks:
33+
34+
```sh
35+
cd bun && bun benchmark
36+
```
737

838
## Usage
9-
The below shows how to use min_pk namespace, should be the same for min_sig.
1039

1140
```zig
12-
pub const min_pk = @import("blst").min_pk;
13-
const SecretKey = min_pk.SecretKey;
41+
pub const blst = @import("blst");
42+
const SecretKey = blst.SecretKey;
1443
const ikm: [32]u8 = [_]u8{
1544
0x93, 0xad, 0x7e, 0x65, 0xde, 0xad, 0x05, 0x2a, 0x08, 0x3a,
1645
0x91, 0x0c, 0x8b, 0x72, 0x85, 0x91, 0x46, 0x4c, 0xca, 0x56,
@@ -27,4 +56,4 @@ const sig = sk.sign(msg[0..], dst[0..], null);
2756
2857
// aug is null
2958
try sig.verify(true, msg[0..], dst[0..], null, &pk, true);
30-
```
59+
```

bun/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"benchmark:files": "bun ./node_modules/.bin/benchmark --config .benchrc.yaml --defaultBranch main"
3131
},
3232
"bun-ffi-z": {
33-
"name": "blst_min_pk",
33+
"name": "eth_blst",
3434
"targets": [
3535
"linux-x64-gnu",
3636
"linux-arm64-gnu",

bun/src/aggregate.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import {binding} from "./binding.js";
2-
import {MAX_AGGREGATE_PER_JOB} from "./const.js";
3-
import {PublicKey, writePublicKeysReference} from "./publicKey.js";
4-
import {Signature, writeSignaturesReference} from "./signature.js";
2+
import {MAX_AGGREGATE_PER_JOB, PUBLIC_KEY_SIZE, SIGNATURE_LENGTH} from "./const.js";
3+
import {PublicKey} from "./publicKey.js";
4+
import {writeSignaturesReference, writePublicKeysReference, writeUint8ArrayArray} from "./writers.ts";
5+
import {writePublicKeys, pksU8, writeSignatures, sigsU8} from "./buffer.ts";
6+
import {Signature} from "./signature.js";
57

68
// global public keys reference to be reused across multiple calls
79
// each 2 items are 8 bytes, store the reference of each public key
810
const publicKeysRef = new Uint32Array(MAX_AGGREGATE_PER_JOB * 2);
9-
1011
const signaturesRef = new Uint32Array(MAX_AGGREGATE_PER_JOB * 2);
1112

1213
/**
@@ -15,6 +16,7 @@ const signaturesRef = new Uint32Array(MAX_AGGREGATE_PER_JOB * 2);
1516
* If `pks_validate` is `true`, the public keys will be infinity and group checked.
1617
*/
1718
export function aggregatePublicKeys(pks: Array<PublicKey>, pksValidate?: boolean | undefined | null): PublicKey {
19+
1820
if (pks.length === 0) {
1921
throw new Error("At least one public key is required");
2022
}
@@ -23,16 +25,17 @@ export function aggregatePublicKeys(pks: Array<PublicKey>, pksValidate?: boolean
2325

2426
for (let i = 0; i < pks.length; i += MAX_AGGREGATE_PER_JOB) {
2527
const pksBatch = pks.slice(i, Math.min(pks.length, i + MAX_AGGREGATE_PER_JOB));
26-
const pksRef = writePublicKeysReference(pksBatch);
27-
const outPk = PublicKey.defaultPublicKey();
28-
const res = binding.aggregatePublicKeys(outPk.ptr, pksRef, pksBatch.length, pksValidate ?? false);
28+
writePublicKeys(pksBatch);
29+
const outPk = new PublicKey(new Uint8Array(PUBLIC_KEY_SIZE));
30+
const res = binding.publicKeyAggregate(outPk.ptr, pksU8, pksBatch.length, pksValidate ?? false);
2931

3032
if (res !== 0) {
3133
throw new Error(`Failed to aggregate public keys: ${res}`);
3234
}
3335
resultPks.push(outPk);
3436
}
3537

38+
3639
return resultPks.length === 1 ? resultPks[0] : aggregatePublicKeys(resultPks, pksValidate);
3740
}
3841

@@ -50,9 +53,9 @@ export function aggregateSignatures(sigs: Array<Signature>, sigsGroupcheck?: boo
5053

5154
for (let i = 0; i < sigs.length; i += MAX_AGGREGATE_PER_JOB) {
5255
const sigsBatch = sigs.slice(i, Math.min(sigs.length, i + MAX_AGGREGATE_PER_JOB));
53-
const sigsRef = writeSignaturesReference(sigsBatch);
54-
const outSig = Signature.defaultSignature();
55-
const res = binding.aggregateSignatures(outSig.ptr, sigsRef, sigsBatch.length, sigsGroupcheck ?? false);
56+
writeSignatures(sigsBatch);
57+
const outSig = new Signature(new Uint8Array(SIGNATURE_LENGTH));
58+
const res = binding.signatureAggregate(outSig.ptr, sigsU8, sigsBatch.length, sigsGroupcheck ?? false);
5659

5760
if (res !== 0) {
5861
throw new Error(`Failed to aggregate signatures: ${res}`);
@@ -81,8 +84,8 @@ export function aggregateSerializedPublicKeys(
8184
for (let i = 0; i < pks.length; i += MAX_AGGREGATE_PER_JOB) {
8285
const pksBatch = pks.slice(i, Math.min(pks.length, i + MAX_AGGREGATE_PER_JOB));
8386
const pksRef = writeSerializedPublicKeysReference(pksBatch);
84-
const outPk = PublicKey.defaultPublicKey();
85-
const res = binding.aggregateSerializedPublicKeys(
87+
const outPk = new PublicKey(new Uint8Array(PUBLIC_KEY_SIZE));
88+
const res = binding.aggregatePublicKeys(
8689
outPk.ptr,
8790
pksRef,
8891
pksBatch.length,
@@ -117,12 +120,11 @@ export function aggregateSerializedSignatures(
117120
for (let i = 0; i < sigs.length; i += MAX_AGGREGATE_PER_JOB) {
118121
const sigsBatch = sigs.slice(i, Math.min(sigs.length, i + MAX_AGGREGATE_PER_JOB));
119122
const sigsRef = writeSerializedSignaturesReference(sigsBatch);
120-
const outSig = Signature.defaultSignature();
121-
const res = binding.aggregateSerializedSignatures(
123+
const outSig = new Signature(new Uint8Array(SIGNATURE_LENGTH));
124+
const res = binding.signatureAggregate(
122125
outSig.ptr,
123126
sigsRef,
124127
sigsBatch.length,
125-
sigs[0].length,
126128
sigsGroupcheck ?? false
127129
);
128130

@@ -132,7 +134,7 @@ export function aggregateSerializedSignatures(
132134
resultSignatures.push(outSig);
133135
}
134136

135-
return resultSignatures.length === 1 ? resultSignatures[0] : aggregateSignatures(resultSignatures, sigsGroupcheck);
137+
return resultSignatures.length === 1 ? resultSignatures[0] : aggregateSerializedSignatures(resultSignatures, sigsGroupcheck);
136138
}
137139

138140
function writeSerializedPublicKeysReference(pks: Uint8Array[]): Uint32Array {

bun/src/aggregateWithRandomness.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import {JSCallback} from "bun:ffi";
2-
import {binding, writeNumber, writeReference} from "./binding.js";
3-
import {MAX_AGGREGATE_WITH_RANDOMNESS_PER_JOB} from "./const.js";
2+
import {binding} from "./binding.js";
3+
import {writePublicKeys, pksU8} from "./buffer.ts";
4+
import {writeReference, writePublicKeysReference, writeSignaturesReference} from "./writers.ts";
5+
import {MAX_AGGREGATE_WITH_RANDOMNESS_PER_JOB, PUBLIC_KEY_SIZE, SIGNATURE_LENGTH} from "./const.js";
46
import {PublicKey} from "./publicKey.js";
57
import {Signature} from "./signature.js";
68

@@ -33,15 +35,17 @@ export function aggregateWithRandomness(sets: Array<PkAndSerializedSig>): PkAndS
3335
throw new Error("At least one PkAndSerializedSig is required");
3436
}
3537

36-
const refs = pkAndSerializedSigsRefs.subarray(0, sets.length * 2);
37-
writePkAndSerializedSigsReference(sets, refs);
38-
const pkOut = PublicKey.defaultPublicKey();
39-
const sigOut = Signature.defaultSignature();
4038

41-
const res = binding.aggregateWithRandomness(refs, sets.length, pkOut.ptr, sigOut.ptr);
39+
const pksRef = writePublicKeysReference(sets.map(s => s.pk));
40+
const sigsRef = writeSignaturesReference(sets.map(s => Signature.fromBytes(s.sig, true)));
41+
const pkOut = new PublicKey(new Uint8Array(PUBLIC_KEY_SIZE));
42+
const sigOut = new Signature(new Uint8Array(SIGNATURE_LENGTH));
4243

43-
if (res !== 0) {
44-
throw new Error("Failed to aggregate with randomness res = " + res);
44+
const resSig = binding.signatureAggregateWithRandomness(sigOut.ptr, sigsRef, sets.length, false);
45+
const resPk = binding.publicKeyAggregateWithRandomness(pkOut.ptr, pksRef, sets.length, false);
46+
47+
if (resSig !== 0 || resPk !== 0) {
48+
throw new Error("Failed to aggregate with randomness res = " + resSig + resPk);
4549
}
4650

4751
return {pk: pkOut, sig: sigOut};
@@ -69,8 +73,8 @@ export function asyncAggregateWithRandomness(sets: Array<PkAndSerializedSig>): P
6973

7074
// 1s timeout
7175
const TIMEOUT_MS = 1_000;
72-
const pkOut = PublicKey.defaultPublicKey();
73-
const sigOut = Signature.defaultSignature();
76+
const pkOut = new PublicKey(new Uint8Array(PUBLIC_KEY_SIZE));
77+
const sigOut = new Signature(new Uint8Array(SIGNATURE_LENGTH));
7478

7579
return new Promise((resolve, reject) => {
7680
let jscallback: JSCallback | null = null;
@@ -111,7 +115,7 @@ export function asyncAggregateWithRandomness(sets: Array<PkAndSerializedSig>): P
111115
const refs = new Uint32Array(sets.length * 2);
112116
writePkAndSerializedSigsReference(sets, refs);
113117

114-
const res = binding.asyncAggregateWithRandomness(
118+
const res = binding.aggregateWithRandomness(
115119
refs,
116120
sets.length,
117121
pkOut.ptr,
@@ -156,7 +160,7 @@ function writePkAndSerializedSigsReference(sets: PkAndSerializedSig[], out: Uint
156160
*
157161
*/
158162
function writePkAndSerializedSigReference(set: PkAndSerializedSig, out: Uint32Array, offset: number): void {
159-
set.pk.writeReference(out, offset);
163+
writeReference(set.pk, out, offset);
160164
writeReference(set.sig, out, offset + 2);
161165
writeNumber(set.sig.length, out, offset + 4);
162166
}

0 commit comments

Comments
 (0)