ringct: txn fee stuff
This commit is contained in:
parent
66f96260b2
commit
f8c04ad94f
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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[])
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue