Skip to content

Commit

Permalink
added more serde methods for pvk
Browse files Browse the repository at this point in the history
  • Loading branch information
mschoenebeck committed Jun 2, 2023
1 parent f9b1836 commit edffafc
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 60 deletions.
18 changes: 12 additions & 6 deletions include/groth16.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,18 @@ namespace groth16
const std::vector<g1>& ic
);
PreparedVerifyingKey(const PreparedVerifyingKey& pvk);
static PreparedVerifyingKey fromBytesBE(const uint8_t* in, const bool check = false, const bool raw = false);
static PreparedVerifyingKey fromBytesLE(const uint8_t* in, const bool check = false, const bool raw = false);
void toBytesBE(uint8_t* out, const bool raw = false) const;
void toBytesLE(uint8_t* out, const bool raw = false) const;
std::vector<uint8_t> toBytesBE(const bool raw = false) const;
std::vector<uint8_t> toBytesLE(const bool raw = false) const;
static PreparedVerifyingKey fromJacobianBytesBE(const uint8_t* in, const bool check = false, const bool raw = false);
static PreparedVerifyingKey fromJacobianBytesLE(const uint8_t* in, const bool check = false, const bool raw = false);
static PreparedVerifyingKey fromAffineBytesBE(const uint8_t* in, const bool check = false, const bool raw = false);
static PreparedVerifyingKey fromAffineBytesLE(const uint8_t* in, const bool check = false, const bool raw = false);
void toJacobianBytesBE(uint8_t* out, const bool raw = false) const;
void toJacobianBytesLE(uint8_t* out, const bool raw = false) const;
void toAffineBytesBE(uint8_t* out, const bool raw = false) const;
void toAffineBytesLE(uint8_t* out, const bool raw = false) const;
std::vector<uint8_t> toJacobianBytesBE(const bool raw = false) const;
std::vector<uint8_t> toJacobianBytesLE(const bool raw = false) const;
std::vector<uint8_t> toAffineBytesBE(const bool raw = false) const;
std::vector<uint8_t> toAffineBytesLE(const bool raw = false) const;
bool equal(const PreparedVerifyingKey& pvk) const;
};

Expand Down
92 changes: 46 additions & 46 deletions src/fp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,12 @@ bool fp::isQuadraticNonResidue() const
bool fp::isLexicographicallyLargest() const
{
array<uint64_t, 6> halfQ = {
0x0D0088F51CBFF34D,
0x258DD3DB21A5D66B,
0xB23BA5C279C2895F,
0xB39869507B587B12,
0x0F55FFFF58A9FFFF,
0xDCFF7FFFFFFFD556
0x0D00'88F5'1CBF'F34D,
0x258D'D3DB'21A5'D66B,
0xB23B'A5C2'79C2'895F,
0xB398'6950'7B58'7B12,
0x0F55'FFFF'58A9'FFFF,
0xDCFF'7FFF'FFFF'D556
};
array<uint64_t, 6> yValue = fromMont().d;

Expand Down Expand Up @@ -296,46 +296,46 @@ const fp fp::B = fp({
});

const fp fp::twoInv = fp({
0x1804000000015554,
0x855000053ab00001,
0x633cb57c253c276f,
0x6e22d1ec31ebb502,
0xd3916126f2d14ca2,
0x17fbb8571a006596
0x1804'0000'0001'5554,
0x8550'0005'3ab0'0001,
0x633c'b57c'253c'276f,
0x6e22'd1ec'31eb'b502,
0xd391'6126'f2d1'4ca2,
0x17fb'b857'1a00'6596
});

const array<uint64_t, 4> fp::Q = {
0xffffffff00000001,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48
0xffff'ffff'0000'0001,
0x53bd'a402'fffe'5bfe,
0x3339'd808'09a1'd805,
0x73ed'a753'299d'7d48
};

const array<uint64_t, 6> fp::pPlus1Over4 = {
0xee7fbfffffffeaab,
0x07aaffffac54ffff,
0xd9cc34a83dac3d89,
0xd91dd2e13ce144af,
0x92c6e9ed90d2eb35,
0x0680447a8e5ff9a6
0xee7f'bfff'ffff'eaab,
0x07aa'ffff'ac54'ffff,
0xd9cc'34a8'3dac'3d89,
0xd91d'd2e1'3ce1'44af,
0x92c6'e9ed'90d2'eb35,
0x0680'447a'8e5f'f9a6
};

const array<uint64_t, 6> fp::pMinus1Over2 = {
0xdcff7fffffffd555,
0x0f55ffff58a9ffff,
0xb39869507b587b12,
0xb23ba5c279c2895f,
0x258dd3db21a5d66b,
0x0d0088f51cbff34d
0xdcff'7fff'ffff'd555,
0x0f55'ffff'58a9'ffff,
0xb398'6950'7b58'7b12,
0xb23b'a5c2'79c2'895f,
0x258d'd3db'21a5'd66b,
0x0d00'88f5'1cbf'f34d
};

const array<uint64_t, 6> fp::pMinus3Over4 = {
0xee7fbfffffffeaaa,
0x07aaffffac54ffff,
0xd9cc34a83dac3d89,
0xd91dd2e13ce144af,
0x92c6e9ed90d2eb35,
0x0680447a8e5ff9a6
0xee7f'bfff'ffff'eaaa,
0x07aa'ffff'ac54'ffff,
0xd9cc'34a8'3dac'3d89,
0xd91d'd2e1'3ce1'44af,
0x92c6'e9ed'90d2'eb35,
0x0680'447a'8e5f'f9a6
};

fp2::fp2() : c0(fp()), c1(fp())
Expand Down Expand Up @@ -646,20 +646,20 @@ bool fp2::isLexicographicallyLargest() const

const fp2 fp2::negativeOne2 = fp2({
fp({
0x43f5fffffffcaaae,
0x32b7fff2ed47fffd,
0x07e83a49a2e99d69,
0xeca8f3318332bb7a,
0xef148d1ea0f4c069,
0x040ab3263eff0206
0x43f5'ffff'fffc'aaae,
0x32b7'fff2'ed47'fffd,
0x07e8'3a49'a2e9'9d69,
0xeca8'f331'8332'bb7a,
0xef14'8d1e'a0f4'c069,
0x040a'b326'3eff'0206
}),
fp({
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
0x0000000000000000
0x0000'0000'0000'0000,
0x0000'0000'0000'0000,
0x0000'0000'0000'0000,
0x0000'0000'0000'0000,
0x0000'0000'0000'0000,
0x0000'0000'0000'0000
}),
});

Expand Down
104 changes: 96 additions & 8 deletions src/groth16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ PreparedVerifyingKey::PreparedVerifyingKey(const PreparedVerifyingKey& pvk) :
{
}

PreparedVerifyingKey PreparedVerifyingKey::fromBytesBE(const uint8_t* in, const bool check, const bool raw)
PreparedVerifyingKey PreparedVerifyingKey::fromJacobianBytesBE(const uint8_t* in, const bool check, const bool raw)
{
fp12 alpha_g1_beta_g2 = fp12::fromBytesBE(span<const uint8_t, 576>(&in[ 0], &in[ 576]), check, raw);
g2 neg_gamma_g2 = g2::fromJacobianBytesBE(span<const uint8_t, 288>(&in[ 576], &in[ 864]), check, raw);
Expand All @@ -505,7 +505,7 @@ PreparedVerifyingKey PreparedVerifyingKey::fromBytesBE(const uint8_t* in, const
);
}

PreparedVerifyingKey PreparedVerifyingKey::fromBytesLE(const uint8_t* in, const bool check, const bool raw)
PreparedVerifyingKey PreparedVerifyingKey::fromJacobianBytesLE(const uint8_t* in, const bool check, const bool raw)
{
fp12 alpha_g1_beta_g2 = fp12::fromBytesLE(span<const uint8_t, 576>(&in[ 0], &in[ 576]), check, raw);
g2 neg_gamma_g2 = g2::fromJacobianBytesLE(span<const uint8_t, 288>(&in[ 576], &in[ 864]), check, raw);
Expand All @@ -525,7 +525,47 @@ PreparedVerifyingKey PreparedVerifyingKey::fromBytesLE(const uint8_t* in, const
);
}

void PreparedVerifyingKey::toBytesBE(uint8_t* out, const bool raw) const
PreparedVerifyingKey PreparedVerifyingKey::fromAffineBytesBE(const uint8_t* in, const bool check, const bool raw)
{
fp12 alpha_g1_beta_g2 = fp12::fromBytesBE(span<const uint8_t, 576>(&in[ 0], &in[576]), check, raw);
g2 neg_gamma_g2 = g2::fromAffineBytesBE(span<const uint8_t, 192>(&in[576], &in[768]), check, raw);
g2 neg_delta_g2 = g2::fromAffineBytesBE(span<const uint8_t, 192>(&in[768], &in[960]), check, raw);
vector<g1> ic;
uint32_t n_ic = in[960] << 24 | in[961] << 16 | in[962] << 8 | in[963];
ic.reserve(n_ic);
for(uint32_t i = 0; i < n_ic; i++)
{
ic.push_back(g1::fromAffineBytesBE(span<const uint8_t, 96>(&in[964 + i*96], &in[964 + (i+1)*96]), check, raw));
}
return PreparedVerifyingKey(
alpha_g1_beta_g2,
neg_gamma_g2,
neg_delta_g2,
ic
);
}

PreparedVerifyingKey PreparedVerifyingKey::fromAffineBytesLE(const uint8_t* in, const bool check, const bool raw)
{
fp12 alpha_g1_beta_g2 = fp12::fromBytesLE(span<const uint8_t, 576>(&in[ 0], &in[576]), check, raw);
g2 neg_gamma_g2 = g2::fromAffineBytesLE(span<const uint8_t, 192>(&in[576], &in[768]), check, raw);
g2 neg_delta_g2 = g2::fromAffineBytesLE(span<const uint8_t, 192>(&in[768], &in[960]), check, raw);
vector<g1> ic;
uint32_t n_ic = in[960] | in[961] << 8 | in[962] << 16 | in[963] << 24;
ic.reserve(n_ic);
for(uint32_t i = 0; i < n_ic; i++)
{
ic.push_back(g1::fromAffineBytesLE(span<const uint8_t, 96>(&in[964 + i*96], &in[964 + (i+1)*96]), check, raw));
}
return PreparedVerifyingKey(
alpha_g1_beta_g2,
neg_gamma_g2,
neg_delta_g2,
ic
);
}

void PreparedVerifyingKey::toJacobianBytesBE(uint8_t* out, const bool raw) const
{
memcpy(&out[ 0], &alpha_g1_beta_g2.toBytesBE(raw)[0], 576);
memcpy(&out[ 576], &neg_gamma_g2.toJacobianBytesBE(raw)[0], 288);
Expand All @@ -541,7 +581,7 @@ void PreparedVerifyingKey::toBytesBE(uint8_t* out, const bool raw) const
}
}

void PreparedVerifyingKey::toBytesLE(uint8_t* out, const bool raw) const
void PreparedVerifyingKey::toJacobianBytesLE(uint8_t* out, const bool raw) const
{
memcpy(&out[ 0], &alpha_g1_beta_g2.toBytesLE(raw)[0], 576);
memcpy(&out[ 576], &neg_gamma_g2.toJacobianBytesLE(raw)[0], 288);
Expand All @@ -557,19 +597,67 @@ void PreparedVerifyingKey::toBytesLE(uint8_t* out, const bool raw) const
}
}

std::vector<uint8_t> PreparedVerifyingKey::toBytesBE(const bool raw) const
void PreparedVerifyingKey::toAffineBytesBE(uint8_t* out, const bool raw) const
{
memcpy(&out[ 0], &alpha_g1_beta_g2.toBytesBE(raw)[0], 576);
memcpy(&out[576], &neg_gamma_g2.toAffineBytesBE(raw)[0], 192);
memcpy(&out[768], &neg_delta_g2.toAffineBytesBE(raw)[0], 192);
uint32_t n_ic = ic.size();
out[960] = n_ic >> 24;
out[961] = n_ic >> 16;
out[962] = n_ic >> 8;
out[963] = n_ic;
for(uint32_t i = 0; i < n_ic; i++)
{
memcpy(&out[964 + i*96], &ic[i].toAffineBytesBE(raw)[0], 96);
}
}

void PreparedVerifyingKey::toAffineBytesLE(uint8_t* out, const bool raw) const
{
memcpy(&out[ 0], &alpha_g1_beta_g2.toBytesLE(raw)[0], 576);
memcpy(&out[576], &neg_gamma_g2.toAffineBytesLE(raw)[0], 192);
memcpy(&out[768], &neg_delta_g2.toAffineBytesLE(raw)[0], 192);
uint32_t n_ic = ic.size();
out[960] = n_ic;
out[961] = n_ic >> 8;
out[962] = n_ic >> 16;
out[963] = n_ic >> 24;
for(uint32_t i = 0; i < n_ic; i++)
{
memcpy(&out[964 + i*96], &ic[i].toAffineBytesLE(raw)[0], 96);
}
}

std::vector<uint8_t> PreparedVerifyingKey::toJacobianBytesBE(const bool raw) const
{
vector<uint8_t> out;
out.resize(1152 + 4 + ic.size()*144);
toBytesBE(out.data(), raw);
toJacobianBytesBE(out.data(), raw);
return out;
}

std::vector<uint8_t> PreparedVerifyingKey::toBytesLE(const bool raw) const
std::vector<uint8_t> PreparedVerifyingKey::toJacobianBytesLE(const bool raw) const
{
vector<uint8_t> out;
out.resize(1152 + 4 + ic.size()*144);
toBytesLE(out.data(), raw);
toJacobianBytesLE(out.data(), raw);
return out;
}

std::vector<uint8_t> PreparedVerifyingKey::toAffineBytesBE(const bool raw) const
{
vector<uint8_t> out;
out.resize(960 + 4 + ic.size()*96);
toAffineBytesBE(out.data(), raw);
return out;
}

std::vector<uint8_t> PreparedVerifyingKey::toAffineBytesLE(const bool raw) const
{
vector<uint8_t> out;
out.resize(960 + 4 + ic.size()*96);
toAffineBytesLE(out.data(), raw);
return out;
}

Expand Down
5 changes: 5 additions & 0 deletions test/unittests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,11 @@ void TestGroth16()
if(!groth16::VerifyingKey::fromCompressedBytesBE(vk.toCompressedBytesBE().data()).equal(vk)) throw invalid_argument("Groth16, vk: CompressedBytesBE error");

groth16::PreparedVerifyingKey pvk = groth16::prepare_verifying_key(vk);
if(!groth16::PreparedVerifyingKey::fromJacobianBytesBE(pvk.toJacobianBytesBE().data()).equal(pvk)) throw invalid_argument("Groth16, pvk: JacobianBytesBE error");
if(!groth16::PreparedVerifyingKey::fromJacobianBytesLE(pvk.toJacobianBytesLE().data()).equal(pvk)) throw invalid_argument("Groth16, pvk: JacobianBytesLE error");
if(!groth16::PreparedVerifyingKey::fromAffineBytesBE(pvk.toAffineBytesBE().data()).equal(pvk)) throw invalid_argument("Groth16, pvk: AffineBytesBE error");
if(!groth16::PreparedVerifyingKey::fromAffineBytesLE(pvk.toAffineBytesLE().data()).equal(pvk)) throw invalid_argument("Groth16, pvk: AffineBytesLE error");

vector<array<uint64_t, 4>> public_inputs = {scalar::fromBytesLE<4>(hexToBytes("2912224b7353476a255f2aeeb0c57b39d5a8e721225bba6620cc2b2011c42245"))};
if(!groth16::verify_proof(pvk, proof, public_inputs)) throw invalid_argument("Groth16: proof invalid");
}
Expand Down

0 comments on commit edffafc

Please sign in to comment.