aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ringct/rctSigs.cpp31
-rw-r--r--src/ringct/rctSigs.h4
-rw-r--r--src/ringct/rctTypes.h2
-rw-r--r--tests/unit_tests/ringct.cpp61
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<xmr_amount> 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<ecdhTuple> 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);
+ vector<xmr_amount >amounts;
+
+
+ //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[])
{