-
-
Notifications
You must be signed in to change notification settings - Fork 353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spend transaction claims #1395
base: master
Are you sure you want to change the base?
Spend transaction claims #1395
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
#include "claim.h" | ||
#include "transcript.h" | ||
|
||
namespace spark { | ||
|
||
Claim::Claim(const GroupElement& F_, const GroupElement& G_, const GroupElement& H_, const GroupElement& U_): | ||
F(F_), G(G_), H(H_), U(U_) { | ||
} | ||
|
||
Scalar Claim::challenge( | ||
const Scalar& mu, | ||
const std::vector<unsigned char>& identifier, | ||
const std::vector<unsigned char>& message, | ||
const std::vector<GroupElement>& S, | ||
const std::vector<GroupElement>& T, | ||
const GroupElement& A1, | ||
const std::vector<GroupElement>& A2 | ||
) { | ||
Transcript transcript(LABEL_TRANSCRIPT_CLAIM); | ||
transcript.add("F", F); | ||
transcript.add("G", G); | ||
transcript.add("H", H); | ||
transcript.add("U", U); | ||
transcript.add("mu", mu); | ||
transcript.add("identifier", identifier); | ||
transcript.add("message", message); | ||
transcript.add("S", S); | ||
transcript.add("T", T); | ||
transcript.add("A1", A1); | ||
transcript.add("A2", A2); | ||
|
||
return transcript.challenge("c"); | ||
} | ||
|
||
void Claim::prove( | ||
const Scalar& mu, | ||
const std::vector<unsigned char>& identifier, | ||
const std::vector<unsigned char>& message, | ||
const std::vector<Scalar>& x, | ||
const std::vector<Scalar>& y, | ||
const std::vector<Scalar>& z, | ||
const std::vector<GroupElement>& S, | ||
const std::vector<GroupElement>& T, | ||
ChaumProof& proof | ||
) { | ||
// Check statement validity | ||
std::size_t n = x.size(); | ||
if (!(y.size() == n && z.size() == n && S.size() == n && T.size() == n)) { | ||
throw std::invalid_argument("Bad claim statement!"); | ||
} | ||
for (std::size_t i = 0; i < n; i++) { | ||
if (!(F*x[i] + G*y[i] + H*z[i] == S[i] && T[i]*x[i] + G*y[i] == U)) { | ||
throw std::invalid_argument("Bad claim statement!"); | ||
} | ||
} | ||
|
||
std::vector<Scalar> r; | ||
r.resize(n); | ||
std::vector<Scalar> s; | ||
s.resize(n); | ||
for (std::size_t i = 0; i < n; i++) { | ||
r[i].randomize(); | ||
s[i].randomize(); | ||
} | ||
Scalar t; | ||
t.randomize(); | ||
|
||
proof.A1 = H*t; | ||
proof.A2.resize(n); | ||
for (std::size_t i = 0; i < n; i++) { | ||
proof.A1 += F*r[i] + G*s[i]; | ||
proof.A2[i] = T[i]*r[i] + G*s[i]; | ||
} | ||
|
||
Scalar c = challenge(mu, identifier, message, S, T, proof.A1, proof.A2); | ||
|
||
proof.t1.resize(n); | ||
proof.t3 = t; | ||
Scalar c_power(c); | ||
for (std::size_t i = 0; i < n; i++) { | ||
if (c_power.isZero()) { | ||
throw std::invalid_argument("Unexpected challenge!"); | ||
} | ||
proof.t1[i] = r[i] + c_power*x[i]; | ||
proof.t2 += s[i] + c_power*y[i]; | ||
proof.t3 += c_power*z[i]; | ||
c_power *= c; | ||
} | ||
} | ||
|
||
bool Claim::verify( | ||
const Scalar& mu, | ||
const std::vector<unsigned char>& identifier, | ||
const std::vector<unsigned char>& message, | ||
const std::vector<GroupElement>& S, | ||
const std::vector<GroupElement>& T, | ||
const ChaumProof& proof | ||
) { | ||
// Check proof semantics | ||
std::size_t n = S.size(); | ||
if (!(T.size() == n && proof.A2.size() == n && proof.t1.size() == n)) { | ||
throw std::invalid_argument("Bad claim semantics!"); | ||
} | ||
|
||
Scalar c = challenge(mu, identifier, message, S, T, proof.A1, proof.A2); | ||
if (c.isZero()) { | ||
throw std::invalid_argument("Unexpected challenge!"); | ||
} | ||
std::vector<Scalar> c_powers; | ||
c_powers.emplace_back(c); | ||
for (std::size_t i = 1; i < n; i++) { | ||
c_powers.emplace_back(c_powers[i-1]*c); | ||
if (c_powers[i].isZero()) { | ||
throw std::invalid_argument("Unexpected challenge!"); | ||
} | ||
} | ||
|
||
// Weight the verification equations | ||
Scalar w; | ||
while (w.isZero()) { | ||
w.randomize(); | ||
} | ||
|
||
std::vector<Scalar> scalars; | ||
std::vector<GroupElement> points; | ||
scalars.reserve(3*n + 5); | ||
points.reserve(3*n + 5); | ||
|
||
// F | ||
Scalar F_scalar; | ||
for (std::size_t i = 0; i < n; i++) { | ||
F_scalar -= proof.t1[i]; | ||
} | ||
scalars.emplace_back(F_scalar); | ||
points.emplace_back(F); | ||
|
||
// G | ||
scalars.emplace_back(proof.t2.negate() - w*proof.t2); | ||
points.emplace_back(G); | ||
|
||
// H | ||
scalars.emplace_back(proof.t3.negate()); | ||
points.emplace_back(H); | ||
|
||
// U | ||
Scalar U_scalar; | ||
for (std::size_t i = 0; i < n; i++) { | ||
U_scalar += c_powers[i]; | ||
} | ||
U_scalar *= w; | ||
scalars.emplace_back(U_scalar); | ||
points.emplace_back(U); | ||
|
||
// A1 | ||
scalars.emplace_back(Scalar((uint64_t) 1)); | ||
points.emplace_back(proof.A1); | ||
|
||
// {A2} | ||
GroupElement A2_sum = proof.A2[0]; | ||
for (std::size_t i = 1; i < n; i++) { | ||
A2_sum += proof.A2[i]; | ||
} | ||
scalars.emplace_back(w); | ||
points.emplace_back(A2_sum); | ||
|
||
// {S} | ||
for (std::size_t i = 0; i < n; i++) { | ||
scalars.emplace_back(c_powers[i]); | ||
points.emplace_back(S[i]); | ||
} | ||
|
||
// {T} | ||
for (std::size_t i = 0; i < n; i++) { | ||
scalars.emplace_back(w.negate()*proof.t1[i]); | ||
points.emplace_back(T[i]); | ||
} | ||
|
||
secp_primitives::MultiExponent multiexp(points, scalars); | ||
// merged equalities and doing check in one multiexponentation, | ||
// for weighting we use random w | ||
return multiexp.get_multiple().isInfinity(); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#ifndef FIRO_LIBSPARK_CLAIM_H | ||
#define FIRO_LIBSPARK_CLAIM_H | ||
|
||
#include "chaum_proof.h" | ||
#include <secp256k1/include/MultiExponent.h> | ||
|
||
namespace spark { | ||
|
||
// A claim proof, which is used to assert control of the consumed coins in a spend transaction | ||
class Claim { | ||
public: | ||
Claim(const GroupElement& F, const GroupElement& G, const GroupElement& H, const GroupElement& U); | ||
|
||
void prove( | ||
const Scalar& mu, | ||
const std::vector<unsigned char>& identifier, | ||
const std::vector<unsigned char>& message, | ||
const std::vector<Scalar>& x, | ||
const std::vector<Scalar>& y, | ||
const std::vector<Scalar>& z, | ||
const std::vector<GroupElement>& S, | ||
const std::vector<GroupElement>& T, | ||
ChaumProof& proof | ||
Comment on lines
+14
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
); | ||
bool verify( | ||
const Scalar& mu, | ||
const std::vector<unsigned char>& identifier, | ||
const std::vector<unsigned char>& message, | ||
const std::vector<GroupElement>& S, | ||
const std::vector<GroupElement>& T, | ||
const ChaumProof& proof | ||
); | ||
|
||
private: | ||
Scalar challenge( | ||
const Scalar& mu, | ||
const std::vector<unsigned char>& identifier, | ||
const std::vector<unsigned char>& message, | ||
const std::vector<GroupElement>& S, | ||
const std::vector<GroupElement>& T, | ||
const GroupElement& A1, | ||
const std::vector<GroupElement>& A2 | ||
); | ||
const GroupElement& F; | ||
const GroupElement& G; | ||
const GroupElement& H; | ||
const GroupElement& U; | ||
}; | ||
|
||
} | ||
|
||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
prove
method includes checks for the validity of the statement being proven. This is a good practice for ensuring the integrity of the input data. However, consider extracting these checks into a separate method to improve code readability and maintainability. Additionally, ensure that error messages provided in exceptions are descriptive enough to help diagnose issues.