ringct: txn fee stuff

This commit is contained in:
Shen Noether 2016-06-12 21:53:01 +01:00 committed by moneromooo-monero
parent 66f96260b2
commit f8c04ad94f
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
4 changed files with 85 additions and 13 deletions

View file

@ -334,7 +334,7 @@ namespace rct {
// this shows that sum inputs = sum outputs // this shows that sum inputs = sum outputs
//Ver: //Ver:
// verifies the above sig is created corretly // 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; mgSig mg;
//setup vars //setup vars
size_t cols = pubs.size(); size_t cols = pubs.size();
@ -372,6 +372,8 @@ namespace rct {
for (size_t j = 0; j < outPk.size(); j++) { 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 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++) { 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.. 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 // this shows that sum inputs = sum outputs
//Ver: //Ver:
// verifies the above sig is created corretly // 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 //setup vars
size_t cols = pubs.size(); size_t cols = pubs.size();
CHECK_AND_ASSERT_THROW_MES(cols >= 1, "Empty pubs"); CHECK_AND_ASSERT_THROW_MES(cols >= 1, "Empty pubs");
@ -410,20 +412,20 @@ namespace rct {
for (j = 0; j < rows; j++) { for (j = 0; j < rows; j++) {
for (i = 0; i < cols; i++) { for (i = 0; i < cols; i++) {
M[i][j] = pubs[i][j].dest; 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++) { for (i = 0; i < cols; i++) {
subKeys(M[i][rows], M[i][rows], outPk[j].mask); 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); key message = cn_fast_hash(outPk);
DP("message:"); DP("message:");
DP(message); DP(message);
return MLSAG_Ver(message, M, mg); return MLSAG_Ver(message, M, mg);
} }
//These functions get keys from blockchain //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) //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 // 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 // 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) { 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() > 0, "Amounts must not be empty");
CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size(), "Different number of amounts/destinations"); 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.mixRing = mixRing;
rv.MG = proveRctMG(rv.mixRing, inSk, outSk, rv.outPk, index); rv.MG = proveRctMG(rv.mixRing, inSk, outSk, rv.outPk, index, txnFeeKey);
if (!verRctMG(rv.MG, rv.mixRing, rv.outPk)) { printf("proveRctMG genreated bad data\n"); }
return rv; return rv;
} }
@ -534,7 +541,9 @@ namespace rct {
DP(tmp); DP(tmp);
rvb = (rvb && 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("mg sig verified?");
DP(mgVerd); DP(mgVerd);

View file

@ -112,8 +112,8 @@ namespace rct {
// this shows that sum inputs = sum outputs // this shows that sum inputs = sum outputs
//Ver: //Ver:
// verifies the above sig is created corretly // verifies the above sig is created corretly
mgSig proveRctMG(const ctkeyM & pubs, const ctkeyV & inSk, const keyV &outMasks, const ctkeyV & outPk, unsigned int index); 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); bool verRctMG(mgSig mg, const ctkeyM & pubs, const ctkeyV & outPk, key txnFee);
//These functions get keys from blockchain //These functions get keys from blockchain
//replace these when connecting blockchain //replace these when connecting blockchain

View file

@ -177,6 +177,7 @@ namespace rct {
//pairs that you mix with //pairs that you mix with
vector<ecdhTuple> ecdhInfo; vector<ecdhTuple> ecdhInfo;
ctkeyV outPk; ctkeyV outPk;
xmr_amount txnFee;
BEGIN_SERIALIZE_OBJECT() BEGIN_SERIALIZE_OBJECT()
FIELD(rangeSigs) FIELD(rangeSigs)
@ -184,6 +185,7 @@ namespace rct {
FIELD(mixRing) FIELD(mixRing)
FIELD(ecdhInfo) FIELD(ecdhInfo)
FIELD(outPk) FIELD(outPk)
FIELD(txnFee)
END_SERIALIZE() END_SERIALIZE()
}; };

View file

@ -213,6 +213,67 @@ TEST(ringct, range_proofs)
ASSERT_TRUE(decodeRct(s, Sk, 1)); 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, static bool range_proof_test(bool expected_valid,
int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[]) int n_inputs, const uint64_t input_amounts[], int n_outputs, const uint64_t output_amounts[])
{ {