You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dateKeys-dart/tool/bls12381_bench.dart

123 lines
4.4 KiB

// Times the BLS12-381 and tlock code of stage 3 (docs/PLAN_dart.md,
// «Rendimiento»): decoding a point of G1 and of G2, one pairing, the
// verification of a Quicknet round signature (hash to G1 and the pairing
// check), the IBE decryption of a tlock stanza, the IBE encryption, and
// steps 10 and 11 of the opening together. On the VM:
//
// dart run tool/bls12381_bench.dart
//
// and compiled to JavaScript, on Node.js, where dart2js reaches the random
// generator through self:
//
// dart compile js -O2 -o bench.js tool/bls12381_bench.dart
// node -e "globalThis.self = globalThis; require('./bench.js')"
//
// Each figure is the median of several runs after one to warm up. The
// program reads no file, so that it runs on the web too.
// ignore_for_file: avoid_print
library;
import 'package:datekeys/datekeys.dart' show fromHex;
import 'package:datekeys/src/bls12381_curve.dart';
import 'package:datekeys/src/bls12381_pairing.dart';
import 'package:datekeys/src/ibe.dart';
import 'package:datekeys/src/release.dart';
import 'package:datekeys/src/tlock.dart';
// The pinned Quicknet profile, as testdata/vectors/profile_quicknet.json.
final class _Quicknet implements PinnedProfile {
@override
String get id => 'datekeys:quicknet:v1';
@override
String get scheme => quicknetScheme;
@override
final publicKey = fromHex(
'83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b'
'6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809'
'bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a',
);
@override
final chainHash = fromHex(
'52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971',
);
@override
int get maxRound => 83903165811;
}
// The releases of rounds 1000 and 1001 (testdata/fixtures/time_only.json and
// empty_payload.json). The runs alternate between them: the last release
// verified is kept (release.dart), and verifying it again costs no pairing.
final _signatures = {
1000: fromHex(
'b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a'
'8dd2bacbe47e4b6b63ed5e39',
),
1001: fromHex(
'b33bf3667cbd5a82de3a24b4e0e9fe5513cc1a0e840368c6e31f5fcfa79bea03f73896b2'
'5883abf2853d10337fb8fa41',
),
};
double _median(List<double> xs) => (xs..sort())[xs.length ~/ 2];
void _time(String name, int runs, void Function(int round) body) {
body(1001);
final ms = <double>[];
for (var i = 0; i < runs; i++) {
final round = i.isEven ? 1000 : 1001;
final sw = Stopwatch()..start();
body(round);
ms.add(sw.elapsedMicroseconds / 1000);
}
print('${name.padRight(48)} ${_median(ms).toStringAsFixed(1)} ms');
}
void main(List<String> args) {
final runs = args.isEmpty ? 7 : int.parse(args.first);
final p = _Quicknet();
Release release(int round) => Release(round, _signatures[round]!);
final sig = G1Point.decode(_signatures[1000]!)!;
final key = G2Point.decode(p.publicKey)!;
final message = fromHex('00112233445566778899aabbccddeeff');
final ct = {
for (final round in [1000, 1001])
round: encryptOnG2(p.publicKey, roundIdentity(round), message),
};
final stanza = {
for (final round in [1000, 1001]) round: wrapTlockStanza(p, round, message),
};
_time('decode a point of G1 (the signature)', runs, (round) {
G1Point.decode(_signatures[round]!);
});
_time('decode a point of G2 (U)', runs, (round) {
G2Point.decode(ct[round]!.u);
});
_time('one pairing', runs, (_) => pairing(sig, key));
// The pinned key is decoded once and kept (pinnedKey of release.dart): the
// first verification pays for it.
_time('verify a Quicknet round signature, key kept', runs, (round) {
verifyRelease(p, round, release(round));
});
_time('the same, decoding the pinned key', runs, (round) {
G2Point.decode(p.publicKey);
verifyRelease(p, round, release(round));
});
_time('IBE decryption of a tlock stanza', runs, (round) {
decryptOnG2(_signatures[round]!, ct[round]!);
});
_time('IBE encryption', runs, (round) {
encryptOnG2(p.publicKey, roundIdentity(round), message);
});
// Steps 10 and 11 of the opening: the release verified, then the stanza
// unwrapped, which verifies the same release again, as Go does.
_time('steps 10 and 11: verify, then unwrap the stanza', runs, (round) {
verifyRelease(p, round, release(round));
final (args, body) = stanza[round]!;
unwrapTlockStanza(p, round, release(round), args, body);
});
}

Powered by TurnKey Linux.