-
-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
373 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,5 @@ obj/*.o | |
sample/*.txt | ||
!sample/CMakeLists.txt | ||
build/ | ||
ffi/zig/.zig-cache/ | ||
ffi/zig/zig-out/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
all: sample | ||
|
||
lib: | ||
make -C ../../ -f Makefile.onelib ETH_CFLAGS=-DBLS_ETH LIB_DIR=lib | ||
|
||
sample: lib | ||
zig build | ||
|
||
run: sample | ||
zig-out/bin/sample | ||
|
||
fmt: | ||
zig fmt *.zig | ||
|
||
test: | ||
zig build test | ||
|
||
clean: | ||
\rm -rf .zig-cache/ zig-out/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
// git clone -b release https://github.com/herumi/bls-eth-go-binary | ||
// cd bls-eth-go-binary | ||
// copy this file into bls | ||
// zig build-exe main.zig -I bls/include/ -L bls/lib/linux/amd64/ -l bls384_256 -l stdc++ -femit-bin=bls.exe && ./bls.exe | ||
|
||
const std = @import("std"); | ||
const bls = @cImport({ | ||
@cDefine("BLS_ETH", ""); | ||
// MCLBN_COMPILED_TIME_VAR should be determined by the definition of BLS_ETH, | ||
// but since this is not working as intended, we explicitly provide a magic number. | ||
@cDefine("MCLBN_COMPILED_TIME_VAR", "246"); | ||
@cInclude("bls/bls384_256.h"); | ||
}); | ||
|
||
pub const MSG_SIZE = 32; | ||
pub const Message = [MSG_SIZE]u8; | ||
|
||
pub const Error = error{ | ||
CantInit, | ||
BufferTooSmall, // serialize, getStr | ||
BufferTooLarge, // setLittleEndianMod, setBigEndianMod | ||
InvalidFormat, // deserialize, setStr | ||
InvalidLength, | ||
}; | ||
|
||
pub fn init() !void { | ||
const res = bls.blsInit(bls.MCL_BLS12_381, bls.MCLBN_COMPILED_TIME_VAR); | ||
if (res != 0) return Error.CantInit; | ||
} | ||
|
||
pub const SecretKey = struct { | ||
v_: bls.blsSecretKey, | ||
pub fn setByCSPRNG(self: *SecretKey) void { | ||
const ret = bls.mclBnFr_setByCSPRNG(&self.v_.v); | ||
if (ret != 0) @panic("mclBnFr_setByCSPRNG"); | ||
} | ||
pub fn serialize(self: *const SecretKey, buf: []u8) ![]u8 { | ||
const len: usize = @intCast(bls.blsSecretKeySerialize(buf.ptr, buf.len, &self.v_)); | ||
if (len == 0) return Error.BufferTooSmall; | ||
return buf[0..len]; | ||
} | ||
pub fn deserialize(self: *SecretKey, buf: []const u8) !void { | ||
const len: usize = @intCast(bls.blsSecretKeyDeserialize(&self.v_, buf.ptr, buf.len)); | ||
if (len == 0 or len != buf.len) return Error.InvalidFormat; | ||
} | ||
// set (buf[] as littleEndian) % r | ||
pub fn setLittleEndianMod(self: *SecretKey, buf: []const u8) !void { | ||
const r = bls.mclBnFr_setLittleEndianMod(&self.v_.v, buf.ptr, buf.len); | ||
if (r < 0) return Error.BufferTooLarge; | ||
} | ||
// set (buf[] as bigEndian) % r | ||
pub fn setBigEndianMod(self: *SecretKey, buf: []const u8) !void { | ||
const r = bls.mclBnFr_setBigEndianMod(&self.v_.v, buf.ptr, buf.len); | ||
if (r < 0) return Error.BufferTooLarge; | ||
} | ||
pub fn setStr(self: *SecretKey, s: []const u8, base: i32) !void { | ||
const r = bls.mclBnFr_setStr(&self.v_.v, s.ptr, s.len, base); | ||
if (r != 0) return Error.InvalidFormat; | ||
} | ||
pub fn getStr(self: *const SecretKey, s: []u8, base: i32) ![]u8 { | ||
const len: usize = @intCast(bls.mclBnFr_getStr(s.ptr, s.len, &self.v_.v, base)); | ||
if (len == 0) return Error.BufferTooSmall; | ||
return s[0..len]; | ||
} | ||
pub fn getPublicKey(self: *const SecretKey, pk: *PublicKey) void { | ||
bls.blsGetPublicKey(&pk.v_, &self.v_); | ||
} | ||
pub fn sign(self: *const SecretKey, sig: *Signature, msg: []const u8) void { | ||
bls.blsSign(&sig.v_, &self.v_, msg.ptr, msg.len); | ||
} | ||
pub fn add(self: *SecretKey, rhs: *const SecretKey) void { | ||
bls.blsSecretKeyAdd(&self.v_, &rhs.v_); | ||
} | ||
}; | ||
|
||
pub const PublicKey = struct { | ||
v_: bls.blsPublicKey, | ||
pub fn serialize(self: *const PublicKey, buf: []u8) ![]u8 { | ||
const len: usize = @intCast(bls.blsPublicKeySerialize(buf.ptr, buf.len, &self.v_)); | ||
if (len == 0) return Error.BufferTooSmall; | ||
return buf[0..len]; | ||
} | ||
pub fn deserialize(self: *PublicKey, buf: []const u8) !void { | ||
const len: usize = @intCast(bls.blsPublicKeyDeserialize(&self.v_, buf.ptr, buf.len)); | ||
if (len == 0 or len != buf.len) return Error.InvalidFormat; | ||
} | ||
pub fn verify(self: *const PublicKey, sig: *const Signature, msg: []const u8) bool { | ||
return bls.blsVerify(&sig.v_, &self.v_, msg.ptr, msg.len) == 1; | ||
} | ||
pub fn add(self: *PublicKey, rhs: *const PublicKey) void { | ||
bls.blsPublicKeyAdd(&self.v_, &rhs.v_); | ||
} | ||
}; | ||
|
||
pub const Signature = struct { | ||
v_: bls.blsSignature, | ||
// Returns a zero-length slice if the function fails. | ||
pub fn serialize(self: *const Signature, buf: []u8) ![]u8 { | ||
const len: usize = @intCast(bls.blsSignatureSerialize(buf.ptr, buf.len, &self.v_)); | ||
if (len == 0) return Error.BufferTooSmall; | ||
return buf[0..len]; | ||
} | ||
pub fn deserialize(self: *Signature, buf: []const u8) !void { | ||
const len: usize = @intCast(bls.blsSignatureDeserialize(&self.v_, buf.ptr, buf.len)); | ||
if (len == 0 or len != buf.len) return Error.InvalidFormat; | ||
} | ||
pub fn add(self: *Signature, rhs: *const Signature) void { | ||
bls.blsSignatureAdd(&self.v_, &rhs.v_); | ||
} | ||
pub fn fastAggregateVerify(self: *const Signature, pubVec: []const PublicKey, msg: []const u8) !bool { | ||
if (pubVec.len == 0) return Error.InvalidLength; | ||
return bls.blsFastAggregateVerify(&self.v_, &pubVec[0].v_, pubVec.len, msg.ptr, msg.len) == 1; | ||
} | ||
pub fn aggregate(self: *Signature, sigVec: []const Signature) !void { | ||
if (sigVec.len == 0) return Error.InvalidLength; | ||
bls.blsAggregateSignature(&self.v_, &sigVec[0].v_, sigVec.len); | ||
} | ||
// Assume that all msgVec are different.. | ||
pub fn aggregateVerifyNocheck(self: *const Signature, pubVec: []const PublicKey, msgVec: []const Message) bool { | ||
const n = pubVec.len; | ||
if (n == 0 or n != msgVec.len) return Error.InvalidLength; | ||
return bls.blsAggregateVerifyNoCheck(&self.v_, &pubVec[0].v_, &msgVec[0][0], MSG_SIZE, n) == 1; | ||
} | ||
// Check whether all msgVec are different.. | ||
pub fn aggregateVerify(self: *const Signature, pubVec: []const PublicKey, msgVec: []const Message) !bool { | ||
const n = pubVec.len; | ||
if (n == 0 or n != msgVec.len) return Error.InvalidLength; | ||
if (!try areAllMessageDifferent(msgVec)) return false; | ||
return bls.blsAggregateVerifyNoCheck(&self.v_, &pubVec[0].v_, &msgVec[0][0], MSG_SIZE, n) == 1; | ||
} | ||
}; | ||
|
||
const MessageComp = struct { | ||
pub fn hash(self: @This(), key: Message) u64 { | ||
_ = self; | ||
return std.hash.Wyhash.hash(0, &key); | ||
} | ||
|
||
pub fn eql(self: @This(), lhs: Message, rhs: Message) bool { | ||
_ = self; | ||
return std.mem.eql(u8, &lhs, &rhs); | ||
} | ||
}; | ||
// Returns true if all msgVec are different. | ||
pub fn areAllMessageDifferent(msgVec: []const Message) !bool { | ||
if (msgVec.len <= 1) return true; | ||
const gpa_allocator = std.heap.page_allocator; | ||
var set = std.HashMap(Message, void, MessageComp, std.hash_map.default_max_load_percentage).init(gpa_allocator); | ||
|
||
defer set.deinit(); | ||
|
||
for (msgVec) |msg| { | ||
const ret = try set.getOrPut(msg); | ||
if (ret.found_existing) return false; | ||
} | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
const std = @import("std"); | ||
|
||
fn setOption(comptime T: type, target: T, b: *std.Build) void { | ||
target.addIncludePath(b.path("../../include")); | ||
target.addIncludePath(b.path("../../mcl/include")); | ||
target.linkLibC(); | ||
target.linkSystemLibrary("stdc++"); | ||
target.addObjectFile(b.path("../../lib/libbls384_256.a")); | ||
} | ||
|
||
pub fn build(b: *std.Build) void { | ||
const target = b.standardTargetOptions(.{}); | ||
const optimize = b.standardOptimizeOption(.{}); | ||
|
||
const lib = b.addStaticLibrary(.{ | ||
.name = "bls-zig", | ||
.root_source_file = b.path("bls.zig"), | ||
.target = target, | ||
.optimize = optimize, | ||
}); | ||
lib.linkLibC(); | ||
lib.addLibraryPath(b.path("../../lib")); | ||
lib.linkSystemLibrary("stdc++"); | ||
lib.linkSystemLibrary("bls384_256"); | ||
b.installArtifact(lib); | ||
|
||
const exe = b.addExecutable(.{ | ||
.name = "sample", | ||
.root_source_file = b.path("sample.zig"), | ||
.target = target, | ||
.optimize = optimize, | ||
}); | ||
|
||
setOption(@TypeOf(exe), exe, b); | ||
|
||
// Make the executable installable | ||
b.installArtifact(exe); | ||
|
||
// Create a run step | ||
const run_cmd = b.addRunArtifact(exe); | ||
run_cmd.step.dependOn(b.getInstallStep()); | ||
const run_step = b.step("run", "Run the example"); | ||
run_step.dependOn(&run_cmd.step); | ||
|
||
// Add test build and run steps | ||
const test_exe = b.addTest(.{ | ||
.root_source_file = b.path("test.zig"), | ||
.target = target, | ||
.optimize = optimize, | ||
}); | ||
setOption(@TypeOf(test_exe), test_exe, b); | ||
|
||
const test_cmd = b.addRunArtifact(test_exe); | ||
test_cmd.step.dependOn(&test_exe.step); | ||
const test_step = b.step("test", "Run the tests"); | ||
test_step.dependOn(&test_cmd.step); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# How to build libbls384_256.a and Zig sample | ||
|
||
``` | ||
git clone --recursive https://github.com/herumi/bls | ||
cd bls | ||
make -f Makefile.onelib ETH_CFLAGS=-DBLS_ETH LIB_DIR=lib | ||
cd ffi/zig | ||
zig build | ||
zig-out/bin/sample | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
const std = @import("std"); | ||
const bls = @import("bls.zig"); | ||
|
||
fn multiSig() !void { | ||
const N = 30; | ||
var skVec: [N]bls.SecretKey = undefined; | ||
var pkVec: [N]bls.PublicKey = undefined; | ||
var sigVec: [N]bls.Signature = undefined; | ||
var sig2Vec: [N]bls.Signature = undefined; | ||
var msgVec: [N]bls.Message = undefined; | ||
const msg = "doremifa"; | ||
for (0..N) |i| { | ||
skVec[i].setByCSPRNG(); | ||
skVec[i].getPublicKey(&pkVec[i]); | ||
skVec[i].sign(&sigVec[i], msg); | ||
if (!pkVec[i].verify(&sigVec[i], msg)) { | ||
std.debug.print("ERR verify i={}\n", .{i}); | ||
return; | ||
} | ||
msgVec[i][0] = @intCast(i & 255); | ||
msgVec[i][1] = @intCast((i >> 8) & 255); | ||
@memset(msgVec[i][2..], 0); | ||
skVec[i].sign(&sig2Vec[i], &msgVec[i]); | ||
} | ||
var agg: bls.Signature = undefined; | ||
try agg.aggregate(&sigVec); | ||
// valid | ||
if (try agg.fastAggregateVerify(&pkVec, msg)) { | ||
std.debug.print("OK fastAggregateVerify\n", .{}); | ||
} else { | ||
std.debug.print("ERR fastAggregateVerify\n", .{}); | ||
return; | ||
} | ||
// invalid | ||
if (!try agg.fastAggregateVerify(pkVec[0 .. N - 1], msg)) { | ||
std.debug.print("OK fastAggregateVerify for invalid pk\n", .{}); | ||
} else { | ||
std.debug.print("ERR fastAggregateVerify\n", .{}); | ||
return; | ||
} | ||
|
||
try agg.aggregate(&sig2Vec); | ||
// valid | ||
if (try agg.aggregateVerify(&pkVec, &msgVec)) { | ||
std.debug.print("OK aggregateVerify\n", .{}); | ||
} else { | ||
std.debug.print("ERR aggregateVerify\n", .{}); | ||
return; | ||
} | ||
// invalid | ||
msgVec[0][0] += 1; | ||
if (!try agg.aggregateVerify(&pkVec, &msgVec)) { | ||
std.debug.print("OK aggregateVerify for invalid msg\n", .{}); | ||
} else { | ||
std.debug.print("ERR aggregateVerify\n", .{}); | ||
return; | ||
} | ||
} | ||
|
||
pub fn main() !void { | ||
try bls.init(); | ||
var sk: bls.SecretKey = undefined; | ||
sk.setByCSPRNG(); | ||
var buf: [128]u8 = undefined; | ||
|
||
const cbuf: []u8 = try sk.serialize(buf[0..]); | ||
std.debug.print("sk:serialize={}\n", .{std.fmt.fmtSliceHexLower(cbuf)}); | ||
var sk2: bls.SecretKey = undefined; | ||
try sk2.deserialize(cbuf); | ||
std.debug.print("sk2:serialize={}\n", .{std.fmt.fmtSliceHexLower(try sk2.serialize(buf[0..]))}); | ||
std.debug.print("sk:getStr(10)={s}\n", .{try sk.getStr(buf[0..], 10)}); | ||
std.debug.print("sk:getStr(16)=0x{s}\n", .{try sk.getStr(buf[0..], 16)}); | ||
try sk.setLittleEndianMod(@as([]const u8, &.{ 1, 2, 3, 4, 5 })); | ||
std.debug.print("sk={s}\n", .{try sk.getStr(buf[0..], 16)}); | ||
try sk.setBigEndianMod(@as([]const u8, &.{ 1, 2, 3, 4, 5 })); | ||
std.debug.print("sk={s}\n", .{try sk.getStr(buf[0..], 16)}); | ||
try sk.setStr("1234567890123", 10); | ||
std.debug.print("sk={s}\n", .{try sk.getStr(buf[0..], 10)}); | ||
var pk: bls.PublicKey = undefined; | ||
sk.getPublicKey(&pk); | ||
std.debug.print("pk={}\n", .{std.fmt.fmtSliceHexLower(try pk.serialize(buf[0..]))}); | ||
const msg = "abcdefg"; | ||
var sig: bls.Signature = undefined; | ||
sk.sign(&sig, msg); | ||
std.debug.print("verify={}\n", .{pk.verify(&sig, msg)}); | ||
std.debug.print("verify={}\n", .{pk.verify(&sig, "abc")}); | ||
try multiSig(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
const std = @import("std"); | ||
const bls = @import("bls.zig"); | ||
|
||
test "init bls" { | ||
try bls.init(); | ||
} | ||
const MSG_N: usize = 258; | ||
|
||
test "all" { | ||
const msg1 = "bls zig test"; | ||
const msg2 = "bls zig te"; | ||
try std.testing.expect(signAndVerifyTest(msg1, msg1)); | ||
try std.testing.expect(!signAndVerifyTest(msg1, msg2)); | ||
try std.testing.expect(try areAllMessageDifferentTest(5)); | ||
try std.testing.expect(try areAllMessageDifferentTest(100)); | ||
try std.testing.expect(try areAllMessageDifferentTest(255)); | ||
try std.testing.expect(try areAllMessageDifferentTest(256)); | ||
try std.testing.expect(!try areAllMessageDifferentTest(257)); // contains the same msg | ||
} | ||
|
||
fn signAndVerifyTest(msg1: []const u8, msg2: []const u8) bool { | ||
var sk: bls.SecretKey = undefined; | ||
var pk: bls.PublicKey = undefined; | ||
var sig: bls.Signature = undefined; | ||
sk.setByCSPRNG(); | ||
sk.getPublicKey(&pk); | ||
sk.sign(&sig, msg1); | ||
return pk.verify(&sig, msg2); | ||
} | ||
|
||
fn areAllMessageDifferentTest(n: usize) !bool { | ||
var msgVec: [MSG_N]bls.Message = undefined; | ||
for (0..MSG_N) |i| { | ||
@memset(&msgVec[i], 0); | ||
msgVec[i][1] = @intCast(i & 255); | ||
} | ||
return bls.areAllMessageDifferent(msgVec[0..n]); | ||
} |
Submodule mcl
updated
17 files
+1 −1 | include/mcl/bn.hpp | |
+86 −50 | include/mcl/ec.hpp | |
+1 −1 | include/mcl/op.hpp | |
+0 −3 | include/mcl/vint.hpp | |
+98 −0 | misc/gather_test.cpp | |
+72 −26 | misc/internal.md | |
+64 −20 | misc/mulvec_test.cpp | |
+12 −8 | readme.md | |
+12 −0 | sample/mt_test.cpp | |
+538 −132 | src/asm/bint-x64-amd64.S | |
+563 −132 | src/asm/bint-x64-mingw.S | |
+561 −132 | src/asm/bint-x64-win.asm | |
+8 −0 | src/avx512.hpp | |
+4 −0 | src/fp.cpp | |
+167 −60 | src/gen_bint_x64.py | |
+431 −146 | src/msm_avx.cpp | |
+32 −0 | test/bls12_test.cpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters