Skip to content

Commit

Permalink
many improvements
Browse files Browse the repository at this point in the history
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
  • Loading branch information
jsign committed Sep 26, 2023
1 parent ab32f33 commit 3e115fb
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 55 deletions.
49 changes: 24 additions & 25 deletions src/bench.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const multiproof = @import("multiproof/multiproof.zig");
const polynomials = @import("polynomial/lagrange_basis.zig");
const ipa = @import("ipa/ipa.zig");
const Transcript = @import("ipa/transcript.zig");
const precomp = @import("crs/msm.zig");

pub fn main() !void {
try benchFields();
Expand Down Expand Up @@ -72,7 +71,6 @@ fn benchFields() !void {

fn benchPedersenHash() !void {
std.debug.print("Benchmarking Pedersen hashing...\n", .{});
const xcrs = crs.CRS.init();
const N = 5000;

var gpa = std.heap.GeneralPurposeAllocator(.{}){};
Expand All @@ -82,8 +80,8 @@ fn benchPedersenHash() !void {
}
var allocator = gpa.allocator();

var precomp_msm = try precomp.PrecompMSM(2, 8, crs.DomainSize).init(allocator, xcrs.Gs);
defer precomp_msm.deinit();
const xcrs = try crs.CRS.init(allocator);
defer xcrs.deinit();

var vec_len: usize = 1;
while (vec_len <= 256) : (vec_len <<= 1) {
Expand All @@ -102,37 +100,37 @@ fn benchPedersenHash() !void {

var start = std.time.microTimestamp();
for (0..N) |i| {
_ = try precomp_msm.msm(vecs[i][0..vec_len]);
_ = try xcrs.commit(vecs[i][0..vec_len]);
}
std.debug.print("takes {}µs\n", .{@divTrunc((std.time.microTimestamp() - start), (N))});
}
}

fn benchIPAs() !void {
const PrecomputedWeights = @import("polynomial/precomputed_weights.zig").PrecomputedWeights(crs.DomainSize, crs.Domain);

std.debug.print("Setting up IPA benchmark...\n", .{});
const N = 100;

var weights = try PrecomputedWeights.init();
const xcrs = crs.CRS.init();
const IPA = ipa.IPA(crs.DomainSize);

std.debug.print("Setting up IPA benchmark...\n", .{});
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer {
const deinit_status = gpa.deinit();
if (deinit_status == .leak) std.testing.expect(false) catch @panic("memory leak");
}
var allocator = gpa.allocator();

var weights = try PrecomputedWeights.init();
const xcrs = try crs.CRS.init(allocator);
defer xcrs.deinit();
const IPA = ipa.IPA(crs.DomainSize);

var prover_queries: []IPA.ProverQuery = try allocator.alloc(IPA.ProverQuery, 16);
defer allocator.free(prover_queries);
const z256 = Fr.fromInteger(256);
for (0..prover_queries.len) |i| {
for (0..prover_queries[i].A.len) |j| {
prover_queries[i].A[j] = Fr.fromInteger(i + j + 0x424242);
}
prover_queries[i].commitment = xcrs.commit(prover_queries[i].A);
prover_queries[i].commitment = try xcrs.commit(&prover_queries[i].A);
prover_queries[i].eval_point = Fr.fromInteger(i + 0x414039).add(z256);
prover_queries[i].B = try weights.barycentricFormulaConstants(prover_queries[i].eval_point);
}
Expand Down Expand Up @@ -177,33 +175,34 @@ fn benchMultiproofs() !void {
const N = 25;
const openings = [_]u16{ 1, 10, 100, 1_000 };

const vkt_crs = crs.CRS.init();

const PolyOpeningSetup = struct {
poly_evaluations: [crs.DomainSize]Fr,
C: banderwagon.Element,
z: Fr,
};

var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer {
const deinit_status = gpa.deinit();
if (deinit_status == .leak) std.testing.expect(false) catch @panic("memory leak");
}
var allocator = gpa.allocator();

const xcrs = try crs.CRS.init(allocator);
defer xcrs.deinit();

const PolyOpeningSetup = struct {
poly_evaluations: [crs.DomainSize]Fr,
C: banderwagon.Element,
z: u8,
};

var vec_openings = try allocator.alloc(PolyOpeningSetup, openings[openings.len - 1]);
defer allocator.free(vec_openings);

for (0..vec_openings.len) |i| {
for (0..vec_openings[i].poly_evaluations.len) |j| {
vec_openings[i].poly_evaluations[j] = Fr.fromInteger(i + j + 0x424242);
}
vec_openings[i].z = Fr.fromInteger((i + 0x414039) % 256);
vec_openings[i].C = crs.CRS.commit(vkt_crs, vec_openings[i].poly_evaluations);
vec_openings[i].z = @truncate(i +% 0x414039);
vec_openings[i].C = try crs.CRS.commit(xcrs, &vec_openings[i].poly_evaluations);
}

const mproof = try multiproof.MultiProof.init(vkt_crs);
const mproof = try multiproof.MultiProof.init(xcrs);
for (openings) |num_openings| {
std.debug.print("\tBenchmarking {} openings...", .{num_openings});

Expand All @@ -218,7 +217,7 @@ fn benchMultiproofs() !void {
.f = LagrangeBasis.init(vec_openings[i].poly_evaluations),
.C = vec_openings[i].C,
.z = vec_openings[i].z,
.y = vec_openings[i].poly_evaluations[@as(usize, @intCast(vec_openings[i].z.toInteger()))],
.y = vec_openings[i].poly_evaluations[vec_openings[i].z],
};
}

Expand All @@ -235,7 +234,7 @@ fn benchMultiproofs() !void {
verifier_queries[i] = multiproof.VerifierQuery{
.C = vec_openings[i].C,
.z = vec_openings[i].z,
.y = vec_openings[i].poly_evaluations[@as(usize, @intCast(vec_openings[i].z.toInteger()))],
.y = vec_openings[i].poly_evaluations[vec_openings[i].z],
};
}
start = std.time.milliTimestamp();
Expand Down
33 changes: 23 additions & 10 deletions src/crs/crs.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const sha256 = std.crypto.hash.sha2.Sha256;
const banderwagon = @import("../banderwagon/banderwagon.zig");
const msm = @import("../msm/msm.zig");
const Element = banderwagon.Element;
const Fr = banderwagon.Fr;

Expand All @@ -20,18 +22,31 @@ pub const Domain: [DomainSize]Fr = domain_elements: {

// CRS contains the base pof points for Pedersen Commitments.
pub const CRS = struct {
const PrecompMSM = msm.PrecompMSM(2, 8);

Gs: [DomainSize]Element,
Q: Element,
precomp: PrecompMSM,

pub fn init() CRS {
pub fn init(allocator: Allocator) !CRS {
const points = deserialize_vkt_points();
return CRS{
.Gs = deserialize_vkt_points(),
.Gs = points,
.Q = Element.generator(),
.precomp = try PrecompMSM.init(allocator, &points),
};
}

pub fn commit(crs: CRS, values: [DomainSize]Fr) Element {
return banderwagon.msm(&crs.Gs, &values);
pub fn deinit(self: CRS) void {
self.precomp.deinit();
}

pub fn commit(self: CRS, values: []const Fr) !Element {
return try self.precomp.msm(values);
}

pub fn commitSlow(self: CRS, values: [DomainSize]Fr) Element {
return banderwagon.msm(&self.Gs, &values);
}
};

Expand All @@ -46,7 +61,8 @@ fn deserialize_vkt_points() [DomainSize]Element {
}

test "crs is consistent" {
const crs = CRS.init();
const crs = try CRS.init(std.testing.allocator);
defer crs.deinit();
try std.testing.expect(crs.Gs.len == vkt_crs_points.len);

// Reserialize Gs points and check they match with the original representation.
Expand All @@ -67,7 +83,8 @@ test "crs is consistent" {
}

test "Gs cannot contain the generator" {
const crs = CRS.init();
const crs = try CRS.init(std.testing.allocator);
defer crs.deinit();
const generator = Element.generator();
for (crs.Gs) |point| {
try std.testing.expect(!generator.equal(point));
Expand Down Expand Up @@ -332,7 +349,3 @@ const vkt_crs_points = [_][]const u8{
"3102a5884d3dce8d94a8cf6d5ab2d3a4c76ec8b00f4554caa68c028aedf5970f",
"3de2be346b539395b0c0de56a5ccca54a317f1b5c80107b0802af9a62276a4d8",
};

test "msm" {
_ = @import("msm.zig");
}
5 changes: 3 additions & 2 deletions src/ipa/ipa.zig
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,9 @@ test "basic proof" {
}

// Commit to the polynomial in lagrange basis
const xcrs = crs.CRS.init();
const commitment = xcrs.commit(lagrange_poly);
const xcrs = try crs.CRS.init(std.testing.allocator);
defer xcrs.deinit();
const commitment = try xcrs.commit(&lagrange_poly);

const expected_comm = std.fmt.bytesToHex(commitment.toBytes(), std.fmt.Case.lower);
try std.testing.expectEqualStrings("1b9dff8f5ebbac250d291dfe90e36283a227c64b113c37f1bfb9e7a743cdb128", &expected_comm);
Expand Down
4 changes: 4 additions & 0 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ test "crs" {
_ = @import("crs/crs.zig");
}

test "msm" {
_ = @import("msm/msm.zig");
}

test "fields" {
_ = @import("fields/fields.zig");
}
Expand Down
28 changes: 17 additions & 11 deletions src/crs/msm.zig → src/msm/msm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const ExtendedPointNormalized = bandersnatch.ExtendedPointNormalized;
pub fn PrecompMSM(
comptime _t: comptime_int,
comptime _b: comptime_int,
comptime basis_len: comptime_int,
) type {
return struct {
const Self = @This();
Expand All @@ -19,16 +18,19 @@ pub fn PrecompMSM(
const t = _t;
const window_size = 1 << b;
const points_per_column = (Fr.BitSize + t - 1) / t;
const num_windows = (points_per_column * basis_len + b - 1) / b;

allocator: Allocator,
table: []const ExtendedPointNormalized,

pub fn init(allocator: Allocator, basis: [basis_len]Element) !Self {
var table_basis = try allocator.alloc(ExtendedPoint, num_windows * basis_len);
num_windows: usize,
basis_len: usize,

pub fn init(allocator: Allocator, basis: []const Element) !Self {
const num_windows = (points_per_column * basis.len + b - 1) / b;
var table_basis = try allocator.alloc(ExtendedPoint, points_per_column * basis.len);
defer allocator.free(table_basis);
var idx: usize = 0;
for (0..basis_len) |hi| {
for (0..basis.len) |hi| {
table_basis[idx] = basis[hi].point;
idx += 1;
for (1..points_per_column) |_| {
Expand Down Expand Up @@ -58,6 +60,8 @@ pub fn PrecompMSM(
return Self{
.allocator = allocator,
.table = table,
.num_windows = num_windows,
.basis_len = basis.len,
};
}

Expand All @@ -66,7 +70,9 @@ pub fn PrecompMSM(
}

pub fn msm(self: Self, mont_scalars: []const Fr) !Element {
std.debug.assert(mont_scalars.len <= basis_len);
if (mont_scalars.len > self.basis_len) {
return error.ScalarLengthBiggerThanBasis;
}

var scalars = try self.allocator.alloc(u256, mont_scalars.len);
defer self.allocator.free(scalars);
Expand Down Expand Up @@ -122,11 +128,11 @@ pub fn PrecompMSM(
}

test "correctness" {
const crs = @import("crs.zig");
const CRS = crs.CRS.init();
var test_allocator = std.testing.allocator;
const crs = @import("../crs/crs.zig");
const xcrs = try crs.CRS.init(std.testing.allocator);
defer xcrs.deinit();

const precomp = try PrecompMSM(2, 5, crs.DomainSize).init(test_allocator, CRS.Gs);
const precomp = try PrecompMSM(2, 5).init(std.testing.allocator, &xcrs.Gs);
defer precomp.deinit();

var scalars: [crs.DomainSize]Fr = undefined;
Expand All @@ -145,7 +151,7 @@ test "correctness" {
}
full_scalars[i] = Fr.zero();
}
const exp = CRS.commit(full_scalars);
const exp = xcrs.commitSlow(full_scalars);
const got = try precomp.msm(msm_scalars);

try std.testing.expect(Element.equal(exp, got));
Expand Down
17 changes: 10 additions & 7 deletions src/multiproof/multiproof.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const Transcript = @import("../ipa/transcript.zig");
const ipa = @import("../ipa/ipa.zig");
const crs = @import("../crs/crs.zig");
const CRS = crs.CRS;
const msm = @import("../msm/msm.zig");
const precomputed_weights = @import("../polynomial/precomputed_weights.zig");

const IPA = ipa.IPA(crs.DomainSize);
Expand Down Expand Up @@ -74,7 +75,7 @@ pub const MultiProof = struct {
power_of_r = Fr.mul(power_of_r, r);
}

const D = CRS.commit(self.crs, g);
const D = try CRS.commit(self.crs, &g);
transcript.appendPoint(D, "D");

// Step 2: Compute h in evaluation form
Expand Down Expand Up @@ -105,7 +106,7 @@ pub const MultiProof = struct {

// Step 3: Evaluate and compute IPA proofs

const E = CRS.commit(self.crs, h);
const E = try CRS.commit(self.crs, &h);
transcript.appendPoint(E, "E");

var ipa_commitment: Element = undefined;
Expand Down Expand Up @@ -203,7 +204,8 @@ pub const MultiProof = struct {
Cs[i] = query.C;
E_coefficients[i] = Fr.mul(powers_of_r[i], helper_scalar_den[queries[i].z]);
}
const E = banderwagon.msm(Cs, E_coefficients);
var precomp = try msm.PrecompMSM(8, 8).init(allocator, Cs);
const E = try precomp.msm(E_coefficients);
transcript.appendPoint(E, "E");

// Check IPA proof.
Expand Down Expand Up @@ -330,9 +332,10 @@ test "basic" {
Fr.fromInteger(1),
} ** 8;

const vkt_crs = CRS.init();
const C_a = CRS.commit(vkt_crs, poly_eval_a);
const C_b = CRS.commit(vkt_crs, poly_eval_b);
const xcrs = try CRS.init(std.testing.allocator);
defer xcrs.deinit();
const C_a = try CRS.commit(xcrs, &poly_eval_a);
const C_b = try CRS.commit(xcrs, &poly_eval_b);
const zs = [_]u8{ 0, 0 };
const ys = [_]Fr{ Fr.fromInteger(1), Fr.fromInteger(32) };
const fs = [_][256]Fr{ poly_eval_a, poly_eval_b };
Expand All @@ -351,7 +354,7 @@ test "basic" {
.y = ys[1],
};

const multiproof = try MultiProof.init(vkt_crs);
const multiproof = try MultiProof.init(xcrs);

var prover_transcript = Transcript.init("test");
const proof = try multiproof.createProof(&prover_transcript, &[_]ProverQuery{ query_a, query_b });
Expand Down

0 comments on commit 3e115fb

Please sign in to comment.