Skip to content

Commit

Permalink
Merge pull request #2 from JusAeng/libspats-balance
Browse files Browse the repository at this point in the history
Libspats balance proof
  • Loading branch information
JusAeng authored Oct 20, 2023
2 parents 03ea2a0 + fd13db6 commit 428566f
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 0 deletions.
54 changes: 54 additions & 0 deletions src/libspats/balance.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "balance.h"
#include "transcript.h"

namespace spats{

Balance::Balance(const GroupElement& E_, const GroupElement& F_, const GroupElement& H_):
E(E_),F(F_),H(H_){
}

Scalar Balance::challenge(
const GroupElement& C,
const GroupElement& A) {
Transcript transcript(LABEL_TRANSCRIPT_BALANCE);
transcript.add("E", E);
transcript.add("F", F);
transcript.add("H", H);
transcript.add("C", C);
transcript.add("A", A);

return transcript.challenge("c");
}

void Balance::prove(const GroupElement& C, const Scalar& w, const Scalar& x, const Scalar& z, BalanceProof& proof) {

if (E*w+F*x+H*z != C){
throw std::invalid_argument("Bad Balance statement!");
}

Scalar rw;
Scalar rx;
Scalar rz;
rw.randomize();
rx.randomize();
rz.randomize();
proof.A = E*rw + F*rx + H*rz;

const Scalar c = challenge(C, proof.A);

proof.tw = rw + c*w;
proof.tx = rx + c*x;
proof.tz = rz + c*z;

}

bool Balance::verify(const GroupElement& C, const BalanceProof& proof) {
const GroupElement check1 = E*proof.tw + F*proof.tx + H*proof.tz;

const Scalar c = challenge(C, proof.A);
const GroupElement check2 = proof.A + C*c;

return (check2+check1.inverse()).isInfinity();
}

}
24 changes: 24 additions & 0 deletions src/libspats/balance.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef FIRO_LIBSPATS_BALANCE_H
#define FIRO_LIBSPATS_BALANCE_H

#include "balance_proof.h"

namespace spats {

class Balance {
public:
Balance(const GroupElement& E, const GroupElement& F, const GroupElement& H);

void prove(const GroupElement& C, const Scalar& w, const Scalar& x, const Scalar& z, BalanceProof& proof);
bool verify(const GroupElement& C, const BalanceProof& proof);

private:
Scalar challenge(const GroupElement& Y, const GroupElement& A);
const GroupElement& E;
const GroupElement& F;
const GroupElement& H;
};

}

#endif
31 changes: 31 additions & 0 deletions src/libspats/balance_proof.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef FIRO_LIBSPATS_BALANCE_PROOF_H
#define FIRO_LIBSPATS_BALANCE_PROOF_H

#include "params.h"

namespace spats{

class BalanceProof{
public:
inline std::size_t memoryRequired() const {
return Scalar::memoryRequired() + GroupElement::memoryRequired();
}

ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(A);
READWRITE(tw);
READWRITE(tx);
READWRITE(tz);
}

public:
GroupElement A;
Scalar tw;
Scalar tx;
Scalar tz;
};
}

#endif
122 changes: 122 additions & 0 deletions src/libspats/test/balance_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include "../balance.h"
#include "../../streams.h"
#include "../../version.h"

#include "../../test/test_bitcoin.h"
#include <boost/test/unit_test.hpp>

namespace spats {

using namespace secp_primitives;

BOOST_FIXTURE_TEST_SUITE(spats_balance_proof_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(serialization)
{
GroupElement E;
E.randomize();
GroupElement F;
F.randomize();
GroupElement H;
H.randomize();

Scalar w;
Scalar x;
Scalar z;
w.randomize();
x.randomize();
z.randomize();

BalanceProof proof;
GroupElement C = E*w+F*x+H*z;

Balance bal(E,F,H);
bal.prove(C, w,x,z, proof);

CDataStream serialized(SER_NETWORK, PROTOCOL_VERSION);
serialized << proof;

BalanceProof deserialized;
serialized >> deserialized;

BOOST_CHECK(proof.A == deserialized.A);
BOOST_CHECK(proof.tw == deserialized.tw);
BOOST_CHECK(proof.tx == deserialized.tx);
BOOST_CHECK(proof.tz == deserialized.tz);
}

BOOST_AUTO_TEST_CASE(completeness)
{
GroupElement E;
E.randomize();
GroupElement F;
F.randomize();
GroupElement H;
H.randomize();

Scalar w;
Scalar x;
Scalar z;
w.randomize();
x.randomize();
z.randomize();

BalanceProof proof;
GroupElement C = E*w+F*x+H*z;

Balance bal(E,F,H);
bal.prove(C,w,x,z,proof);

// Verify
BOOST_CHECK(bal.verify(C,proof));
}

BOOST_AUTO_TEST_CASE(bad_proofs)
{
GroupElement E;
E.randomize();
GroupElement F;
F.randomize();
GroupElement H;
H.randomize();

Scalar w;
Scalar x;
Scalar z;
w.randomize();
x.randomize();
z.randomize();

BalanceProof proof;
GroupElement C = E*w+F*x+H*z;

Balance bal(E,F,H);
bal.prove(C,w,x,z,proof);

// Bad C
GroupElement evil_C;
evil_C.randomize();
BOOST_CHECK(!(bal.verify(evil_C, proof)));

// Bad A
BalanceProof evil_proof = proof;
evil_proof.A.randomize();
BOOST_CHECK(!(bal.verify(C, evil_proof)));

// Bad tw
evil_proof = proof;
evil_proof.tw.randomize();
BOOST_CHECK(!(bal.verify(C, evil_proof)));
// Bad tx
evil_proof = proof;
evil_proof.tx.randomize();
BOOST_CHECK(!(bal.verify(C, evil_proof)));
// Bad tz
evil_proof = proof;
evil_proof.tz.randomize();
BOOST_CHECK(!(bal.verify(C, evil_proof)));
}

BOOST_AUTO_TEST_SUITE_END()

}
2 changes: 2 additions & 0 deletions src/libspats/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const std::string LABEL_TRANSCRIPT_BPPLUS = "BULLETPROOF_PLUS_V1";
const std::string LABEL_TRANSCRIPT_CHAUM = "CHAUM_V1";
const std::string LABEL_TRANSCRIPT_GROOTLE = "GROOTLE_V1";
const std::string LABEL_TRANSCRIPT_SCHNORR = "SCHNORR_V1";
const std::string LABEL_TRANSCRIPT_BALANCE = "BALANCE_V1";


// Generator labels
const std::string LABEL_GENERATOR_E = "E";
Expand Down

0 comments on commit 428566f

Please sign in to comment.