Skip to content

Commit

Permalink
port:native pedersen hash func (keep-starknet-strange#310)
Browse files Browse the repository at this point in the history
* native poseidon hashing func

* comment for constants

* removed unused commented func in fields

* code generation for poseidon round key consts

* small refactoring

* native pedersen hashing func with const point generator

* fix conflicts

* additional comments

* additional comment

* style fixes

* style fixes

* style fixes

* small fixes

---------

Co-authored-by: lanaivina <[email protected]>
  • Loading branch information
StringNick and lana-shanghai authored Jan 19, 2024
1 parent 48c208e commit 842ff1a
Show file tree
Hide file tree
Showing 10 changed files with 36,442 additions and 12 deletions.
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ test-filter: libstarknet_crypto.a
build-integration-test:
@zig build integration_test

build-and-run-pedersen-table-gen:
@zig build pedersen_table_gen
> ./src/math/crypto/pedersen/gen/constants.zig
./zig-out/bin/pedersen_table_gen
@zig fmt ./src/math/crypto/pedersen/gen/constants.zig

build-and-run-poseidon-consts-gen:
@zig build poseidon_consts_gen
> ./src/math/crypto/poseidon/gen/constants.zig
Expand Down
23 changes: 23 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ pub fn build(b: *std.Build) void {
// and can be selected like this: `zig build poseidon_consts_gen`
poseidon_consts_gen(b, optimize, target);

// This creates a build step. It will be visible in the `zig build --help` menu,
// and can be selected like this: `zig build pedersen_table_gen`
pedersen_table_gen(b, optimize, target);

// This creates a build step. It will be visible in the `zig build --help` menu,
// and can be selected like this: `zig build run`
// This will evaluate the `run` step rather than the default, which is "install".
Expand Down Expand Up @@ -203,3 +207,22 @@ fn poseidon_consts_gen(
const install_step = b.addInstallArtifact(binary, .{});
poseidon_consts_gen_build.dependOn(&install_step.step);
}

fn pedersen_table_gen(
b: *std.Build,
mode: std.builtin.Mode,
target: std.Build.ResolvedTarget,
) void {
const binary = b.addExecutable(.{
.name = "pedersen_table_gen",
.root_source_file = .{ .path = "src/pedersen_table_gen.zig" },
.target = target,
.optimize = mode,
});

const pedersen_table_gen_build = b.step("pedersen_table_gen", "Cli: pedersen table generator");
pedersen_table_gen_build.dependOn(&binary.step);

const install_step = b.addInstallArtifact(binary, .{});
pedersen_table_gen_build.dependOn(&install_step.step);
}
1 change: 1 addition & 0 deletions src/lib.zig
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub const math = struct {
pub usingnamespace @import("math/fields/stark_felt_252_gen_fp.zig");
pub usingnamespace @import("math/fields/starknet.zig");
pub usingnamespace @import("math/crypto/poseidon/poseidon.zig");
pub usingnamespace @import("math/crypto/pedersen/pedersen.zig");

pub usingnamespace @import("math/crypto/pedersen_hash.zig");
pub usingnamespace @import("math/fields/elliptic_curve.zig");
Expand Down
148 changes: 148 additions & 0 deletions src/math/crypto/curve/curve_params.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// code ported from starknet-curve:
// https://github.com/xJonathanLEI/starknet-rs/blob/0857bd6cd3bd34cbb06708f0a185757044171d8d/starknet-curve/src/curve_params.rs
const Felt252 = @import("../../fields/starknet.zig").Felt252;
const AffinePoint = @import("ec_point.zig").AffinePoint;

pub const EC_ORDER: Felt252 = .{
.fe = [4]u64{
8939893405601011193,
1143265896874747514,
9,
369010039416812937,
},
};
pub const ALPHA: Felt252 = .{
.fe = [4]u64{
18446744073709551585,
18446744073709551615,
18446744073709551615,
576460752303422960,
},
};

pub const BETA: Felt252 = .{
.fe = [4]u64{
3863487492851900874,
7432612994240712710,
12360725113329547591,
88155977965380735,
},
};

pub const GENERATOR: AffinePoint = .{
.x = .{
.fe = [4]u64{
14484022957141291997,
5884444832209845738,
299981207024966779,
232005955912912577,
},
},
.y = .{
.fe = [4]u64{
6241159653446987914,
664812301889158119,
18147424675297964973,
405578048423154473,
},
},
.infinity = false,
};

pub const SHIFT_POINT: AffinePoint = .{
.x = .{ .fe = [4]u64{
1933903796324928314,
7739989395386261137,
1641324389046377921,
316327189671755572,
} },
.y = .{
.fe = [4]u64{
14252083571674603243,
12587053260418384210,
4798858472748676776,
81375596133053150,
},
},
.infinity = false,
};

pub const PEDERSEN_P0: AffinePoint = .{
.x = .{
.fe = [4]u64{
3602345268353203007,
13758484295849329960,
518715844721862878,
241691544791834578,
},
},
.y = .{
.fe = [4]u64{
13441546676070136227,
13001553326386915570,
433857700841878496,
368891789801938570,
},
},
.infinity = false,
};

pub const PEDERSEN_P1: AffinePoint = .{
.x = .{
.fe = [4]u64{
16491878934996302286,
12382025591154462459,
10043949394709899044,
253000153565733272,
},
},
.y = .{
.fe = [4]u64{
13950428914333633429,
2545498000137298346,
5191292837124484988,
285630633187035523,
},
},
.infinity = false,
};

pub const PEDERSEN_P2: AffinePoint = .{
.x = .{
.fe = [4]u64{
1203723169299412240,
18195981508842736832,
12916675983929588442,
338510149841406402,
},
},
.y = .{
.fe = [4]u64{
12352616181161700245,
11743524503750604092,
11088962269971685343,
161068411212710156,
},
},
.infinity = false,
};

pub const PEDERSEN_P3: AffinePoint = .{
.x = .{
.fe = [4]u64{
1145636535101238356,
10664803185694787051,
299781701614706065,
425493972656615276,
},
},
.y = .{
.fe = [4]u64{
8187986478389849302,
4428713245976508844,
6033691581221864148,
345457391846365716,
},
},
.infinity = false,
};
155 changes: 155 additions & 0 deletions src/math/crypto/curve/ec_point.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// code ported from starknet-curve:
// https://github.com/xJonathanLEI/starknet-rs/blob/0857bd6cd3bd34cbb06708f0a185757044171d8d/starknet-curve/src/ec_point.rs
const Felt252 = @import("../../fields/starknet.zig").Felt252;
const ALPHA = @import("./curve_params.zig").ALPHA;
const BETA = @import("./curve_params.zig").BETA;

pub const ProjectivePoint = struct {
const Self = @This();

x: Felt252,
y: Felt252,
z: Felt252 = Felt252.one(),
infinity: bool = false,

pub fn fromAffinePoint(p: AffinePoint) Self {
return .{
.x = p.x,
.y = p.y,
};
}

pub fn doubleAssign(self: *Self) void {
if (self.infinity) {
return;
}

// t=3x^2+az^2 with a=1 from stark curve
const t = Felt252.three().mul(self.x).mul(self.x).add(self.z.mul(self.z));
const u = Felt252.two().mul(self.y).mul(self.z);
const v = Felt252.two().mul(u).mul(self.x).mul(self.y);
const w = t.mul(t).sub(Felt252.two().mul(v));

const uy = u.mul(self.y);

self.* = .{
.x = u.mul(w),
.y = t.mul(v.sub(w)).sub(Felt252.two().mul(uy).mul(uy)),
.z = u.mul(u).mul(u),
.infinity = self.infinity,
};
}

pub fn addAssignAffinePoint(self: *Self, rhs: AffinePoint) void {
if (rhs.infinity) {
return;
}

if (self.infinity) {
self.* = .{
.x = rhs.x,
.y = rhs.y,
.z = Felt252.one(),
.infinity = rhs.infinity,
};
return;
}

const u_0 = self.x;
const u_1 = rhs.x.mul(self.z);
const t0 = self.y;
const t1 = rhs.y.mul(self.z);

if (u_0.equal(u_1)) {
if (!t0.equal(t1)) {
self.infinity = true;
} else {
self.doubleAssign();
}
return;
}

const t = t0.sub(t1);
const u = u_0.sub(u_1);
const u_2 = u.mul(u);

const v = self.z;
const w = t.mul(t).mul(v).sub(u_2.mul(u_0.add(u_1)));
const u_3 = u.mul(u_2);

const x = u.mul(w);
const y = t.mul(u_0.mul(u_2).sub(w)).sub(t0.mul(u_3));
const z = u_3.mul(v);

self.* = .{
.x = x,
.y = y,
.z = z,
.infinity = self.infinity,
};
}
};

pub const AffinePoint = struct {
const Self = @This();
x: Felt252,
y: Felt252,
infinity: bool,

// TODO: think about from_x method, dont implemented right now, because need to implemented
// sqrt method for Felt252

pub fn addAssign(self: *Self, rhs: *AffinePoint) void {
if (rhs.infinity) {
return;
}
if (self.infinity) {
self.x = rhs.x;
self.y = rhs.y;
self.infinity = rhs.infinity;
return;
}

if (self.x.equal(rhs.x)) {
if (self.y.equal(rhs.y.neg())) {
self.x = Felt252.zero();
self.y = Felt252.zero();
self.infinity = true;
return;
}
self.doubleAssign();
return;
}

// l = (y2-y1)/(x2-x1)
const lambda = rhs.y.sub(self.y).mul(rhs.x.sub(self.x).inv().?);

const result_x = lambda.mul(lambda).sub(self.x).sub(rhs.x);
self.y = lambda.mul(self.x.sub(result_x)).sub(self.y);
self.x = result_x;
}

pub fn doubleAssign(self: *Self) void {
if (self.infinity) {
return;
}

// l = (3x^2+a)/2y with a=1 from stark curve
const lambda = Felt252.three().mul(self.x.mul(self.x)).add(Felt252.one()).mul(Felt252.two().mul(self.y).inv().?);

const result_x = lambda.mul(lambda).sub(self.x).sub(self.x);
self.y = lambda.mul(self.x.sub(result_x)).sub(self.y);
self.x = result_x;
}

pub fn fromProjectivePoint(p: *ProjectivePoint) Self {
// always one, that is why we can unwrap, unreachable will not happen
const zinv = if (p.z.inv()) |zinv| zinv else unreachable;

return .{
.x = p.x.mul(zinv),
.y = p.y.mul(zinv),
.infinity = false,
};
}
};
Loading

0 comments on commit 842ff1a

Please sign in to comment.