From f8c04ad94fff9df079b59f197a49e19478385725 Mon Sep 17 00:00:00 2001 From: Shen Noether Date: Sun, 12 Jun 2016 21:53:01 +0100 Subject: [PATCH] ringct: txn fee stuff --- src/ringct/rctSigs.cpp | 31 ++++++++++++------- src/ringct/rctSigs.h | 4 +-- src/ringct/rctTypes.h | 2 ++ tests/unit_tests/ringct.cpp | 61 +++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 13 deletions(-) diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index f1ffa2702..53cb1ab6f 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -334,7 +334,7 @@ namespace rct { // this shows that sum inputs = sum outputs //Ver: // verifies the above sig is created corretly - mgSig proveRctMG(const ctkeyM & pubs, const ctkeyV & inSk, const ctkeyV &outSk, const ctkeyV & outPk, unsigned int index) { + mgSig proveRctMG(const ctkeyM & pubs, const ctkeyV & inSk, const ctkeyV &outSk, const ctkeyV & outPk, unsigned int index, key txnFeeKey) { mgSig mg; //setup vars size_t cols = pubs.size(); @@ -372,6 +372,8 @@ namespace rct { for (size_t j = 0; j < outPk.size(); j++) { subKeys(M[i][rows], M[i][rows], outPk[j].mask); //subtract output Ci's in last row } + //subtract txn fee output in last row + subKeys(M[i][rows], M[i][rows], txnFeeKey); } for (size_t j = 0; j < outPk.size(); j++) { sc_sub(sk[rows].bytes, sk[rows].bytes, outSk[j].mask.bytes); //subtract output masks in last row.. @@ -389,7 +391,7 @@ namespace rct { // this shows that sum inputs = sum outputs //Ver: // verifies the above sig is created corretly - bool verRctMG(mgSig mg, const ctkeyM & pubs, const ctkeyV & outPk) { + bool verRctMG(mgSig mg, const ctkeyM & pubs, const ctkeyV & outPk, key txnFeeKey) { //setup vars size_t cols = pubs.size(); CHECK_AND_ASSERT_THROW_MES(cols >= 1, "Empty pubs"); @@ -410,20 +412,20 @@ namespace rct { for (j = 0; j < rows; j++) { for (i = 0; i < cols; i++) { M[i][j] = pubs[i][j].dest; - addKeys(M[i][rows], M[i][rows], pubs[i][j].mask); + addKeys(M[i][rows], M[i][rows], pubs[i][j].mask); //add Ci in last row } } - for (size_t j = 0; j < outPk.size(); j++) { - for (i = 0; i < cols; i++) { - subKeys(M[i][rows], M[i][rows], outPk[j].mask); + for (i = 0; i < cols; i++) { + for (j = 0; j < outPk.size(); j++) { + subKeys(M[i][rows], M[i][rows], outPk[j].mask); //subtract output Ci's in last row } - + //subtract txn fee output in last row + subKeys(M[i][rows], M[i][rows], txnFeeKey); } key message = cn_fast_hash(outPk); DP("message:"); DP(message); return MLSAG_Ver(message, M, mg); - } //These functions get keys from blockchain @@ -466,6 +468,8 @@ namespace rct { //decodeRct: (c.f. http://eprint.iacr.org/2015/1098 section 5.1.1) // uses the attached ecdh info to find the amounts represented by each output commitment // must know the destination private key to find the correct amount, else will return a random number + // Note: For txn fees, the last index in the amounts vector should contain that + // Thus the amounts vector will be "one" longer than the destinations vectort rctSig genRct(const ctkeyV & inSk, const keyV & destinations, const vector amounts, const ctkeyM &mixRing, unsigned int index) { CHECK_AND_ASSERT_THROW_MES(amounts.size() > 0, "Amounts must not be empty"); CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size(), "Different number of amounts/destinations"); @@ -498,9 +502,12 @@ namespace rct { } + //set txn fee + rv.txnFee = amounts[destinations.size()]; + key txnFeeKey = scalarmultH(d2h(rv.txnFee)); + rv.mixRing = mixRing; - rv.MG = proveRctMG(rv.mixRing, inSk, outSk, rv.outPk, index); - if (!verRctMG(rv.MG, rv.mixRing, rv.outPk)) { printf("proveRctMG genreated bad data\n"); } + rv.MG = proveRctMG(rv.mixRing, inSk, outSk, rv.outPk, index, txnFeeKey); return rv; } @@ -534,7 +541,9 @@ namespace rct { DP(tmp); rvb = (rvb && tmp); } - bool mgVerd = verRctMG(rv.MG, rv.mixRing, rv.outPk); + //compute txn fee + key txnFeeKey = scalarmultH(d2h(rv.txnFee)); + bool mgVerd = verRctMG(rv.MG, rv.mixRing, rv.outPk, txnFeeKey); DP("mg sig verified?"); DP(mgVerd); diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index a7306bc31..d5c036910 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -112,8 +112,8 @@ namespace rct { // this shows that sum inputs = sum outputs //Ver: // verifies the above sig is created corretly - mgSig proveRctMG(const ctkeyM & pubs, const ctkeyV & inSk, const keyV &outMasks, const ctkeyV & outPk, unsigned int index); - bool verRctMG(mgSig mg, const ctkeyM & pubs, const ctkeyV & outPk); + mgSig proveRctMG(const ctkeyM & pubs, const ctkeyV & inSk, const keyV &outMasks, const ctkeyV & outPk, unsigned int index, key txnFee); + bool verRctMG(mgSig mg, const ctkeyM & pubs, const ctkeyV & outPk, key txnFee); //These functions get keys from blockchain //replace these when connecting blockchain diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 21bcf4da2..01585235f 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -177,6 +177,7 @@ namespace rct { //pairs that you mix with vector ecdhInfo; ctkeyV outPk; + xmr_amount txnFee; BEGIN_SERIALIZE_OBJECT() FIELD(rangeSigs) @@ -184,6 +185,7 @@ namespace rct { FIELD(mixRing) FIELD(ecdhInfo) FIELD(outPk) + FIELD(txnFee) END_SERIALIZE() }; diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index 13dc313dd..ba9d3ecc4 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -213,6 +213,67 @@ TEST(ringct, range_proofs) ASSERT_TRUE(decodeRct(s, Sk, 1)); } +TEST(ringct, range_proofs_with_fee) +{ + //Ring CT Stuff + //ct range proofs + ctkeyV sc, pc; + ctkey sctmp, pctmp; + //add fake input 5000 + tie(sctmp, pctmp) = ctskpkGen(6001); + sc.push_back(sctmp); + pc.push_back(pctmp); + + + tie(sctmp, pctmp) = ctskpkGen(7000); + sc.push_back(sctmp); + pc.push_back(pctmp); + vectoramounts; + + + //add output 500 + amounts.push_back(500); + keyV destinations; + key Sk, Pk; + skpkGen(Sk, Pk); + destinations.push_back(Pk); + + //add txn fee for 1 + //has no corresponding destination.. + amounts.push_back(1); + + //add output for 12500 + amounts.push_back(12500); + skpkGen(Sk, Pk); + destinations.push_back(Pk); + + //compute rct data with mixin 500 + rctSig s = genRct(sc, pc, destinations, amounts, 3); + + //verify rct data + ASSERT_TRUE(verRct(s)); + + //decode received amount + ASSERT_TRUE(decodeRct(s, Sk, 1)); + + // Ring CT with failing MG sig part should not verify! + // Since sum of inputs != outputs + + amounts[1] = 12501; + skpkGen(Sk, Pk); + destinations[1] = Pk; + + + //compute rct data with mixin 500 + s = genRct(sc, pc, destinations, amounts, 3); + + //verify rct data + ASSERT_FALSE(verRct(s)); + + //decode received amount + ASSERT_TRUE(decodeRct(s, Sk, 1)); +} + static bool range_proof_test(bool expected_valid, int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[]) {