aboutsummaryrefslogtreecommitdiff
path: root/src/ringct
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2019-01-08 16:05:18 +0000
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2019-02-12 12:16:47 +0000
commit0b18fa54c458ee8d76382963ffe5d14af6c11390 (patch)
treeafe837566e042566afc33c179f82b7f4c6f29a28 /src/ringct
parentringct: encode 8 byte amount, saving 24 bytes per output (diff)
downloadmonero-0b18fa54c458ee8d76382963ffe5d14af6c11390.tar.xz
ringct: the commitment mask is now deterministic
saves space in the tx and is safe Found by knaccc
Diffstat (limited to 'src/ringct')
-rw-r--r--src/ringct/rctOps.cpp56
-rw-r--r--src/ringct/rctOps.h5
-rw-r--r--src/ringct/rctSigs.cpp24
-rw-r--r--src/ringct/rctTypes.h3
4 files changed, 53 insertions, 35 deletions
diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp
index b4609caab..747b686cd 100644
--- a/src/ringct/rctOps.cpp
+++ b/src/ringct/rctOps.cpp
@@ -489,36 +489,56 @@ namespace rct {
// where C= aG + bH
static key ecdhHash(const key &k)
{
- char data[38];
- rct::key hash;
- memcpy(data, "amount", 6);
- memcpy(data + 6, &k, sizeof(k));
- cn_fast_hash(hash, data, sizeof(data));
- return hash;
+ char data[38];
+ rct::key hash;
+ memcpy(data, "amount", 6);
+ memcpy(data + 6, &k, sizeof(k));
+ cn_fast_hash(hash, data, sizeof(data));
+ return hash;
}
static void xor8(key &v, const key &k)
{
- for (int i = 0; i < 8; ++i)
- v.bytes[i] ^= k.bytes[i];
+ for (int i = 0; i < 8; ++i)
+ v.bytes[i] ^= k.bytes[i];
+ }
+ key genCommitmentMask(const key &sk)
+ {
+ char data[15 + sizeof(key)];
+ memcpy(data, "commitment_mask", 15);
+ memcpy(data + 15, &sk, sizeof(sk));
+ key scalar;
+ hash_to_scalar(scalar, data, sizeof(data));
+ return scalar;
}
- void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, bool short_amount) {
- key sharedSec1 = hash_to_scalar(sharedSec);
- key sharedSec2 = hash_to_scalar(sharedSec1);
+
+ void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, bool v2) {
//encode
- sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes);
- if (short_amount)
+ if (v2)
+ {
+ unmasked.mask = zero();
xor8(unmasked.amount, ecdhHash(sharedSec));
+ }
else
+ {
+ key sharedSec1 = hash_to_scalar(sharedSec);
+ key sharedSec2 = hash_to_scalar(sharedSec1);
+ sc_add(unmasked.mask.bytes, unmasked.mask.bytes, sharedSec1.bytes);
sc_add(unmasked.amount.bytes, unmasked.amount.bytes, sharedSec2.bytes);
+ }
}
- void ecdhDecode(ecdhTuple & masked, const key & sharedSec, bool short_amount) {
- key sharedSec1 = hash_to_scalar(sharedSec);
- key sharedSec2 = hash_to_scalar(sharedSec1);
+ void ecdhDecode(ecdhTuple & masked, const key & sharedSec, bool v2) {
//decode
- sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes);
- if (short_amount)
+ if (v2)
+ {
+ masked.mask = genCommitmentMask(sharedSec);
xor8(masked.amount, ecdhHash(sharedSec));
+ }
else
+ {
+ key sharedSec1 = hash_to_scalar(sharedSec);
+ key sharedSec2 = hash_to_scalar(sharedSec1);
+ sc_sub(masked.mask.bytes, masked.mask.bytes, sharedSec1.bytes);
sc_sub(masked.amount.bytes, masked.amount.bytes, sharedSec2.bytes);
+ }
}
}
diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h
index 01cdd6fd7..dd6d87593 100644
--- a/src/ringct/rctOps.h
+++ b/src/ringct/rctOps.h
@@ -182,7 +182,8 @@ namespace rct {
//Elliptic Curve Diffie Helman: encodes and decodes the amount b and mask a
// where C= aG + bH
- void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, bool short_amount);
- void ecdhDecode(ecdhTuple & masked, const key & sharedSec, bool short_amount);
+ key genCommitmentMask(const key &sk);
+ void ecdhEncode(ecdhTuple & unmasked, const key & sharedSec, bool v2);
+ void ecdhDecode(ecdhTuple & masked, const key & sharedSec, bool v2);
}
#endif /* RCTOPS_H */
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index 28d523e4f..a9f6d6a53 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -45,18 +45,12 @@ using namespace std;
#define CHECK_AND_ASSERT_MES_L1(expr, ret, message) {if(!(expr)) {MCERROR("verify", message); return ret;}}
namespace rct {
- Bulletproof proveRangeBulletproof(key &C, key &mask, uint64_t amount)
+ Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, const std::vector<key> &sk)
{
- mask = rct::skGen();
- Bulletproof proof = bulletproof_PROVE(amount, mask);
- CHECK_AND_ASSERT_THROW_MES(proof.V.size() == 1, "V has not exactly one element");
- C = proof.V[0];
- return proof;
- }
-
- Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts)
- {
- masks = rct::skvGen(amounts.size());
+ CHECK_AND_ASSERT_THROW_MES(amounts.size() == sk.size(), "Invalid amounts/sk sizes");
+ masks.resize(amounts.size());
+ for (size_t i = 0; i < masks.size(); ++i)
+ masks[i] = genCommitmentMask(sk[i]);
Bulletproof proof = bulletproof_PROVE(amounts, masks);
CHECK_AND_ASSERT_THROW_MES(proof.V.size() == amounts.size(), "V does not have the expected size");
C = proof.V;
@@ -762,7 +756,8 @@ namespace rct {
if (rct_config.range_proof_type == RangeProofPaddedBulletproof)
{
rct::keyV C, masks;
- rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts));
+ const std::vector<key> keys(amount_keys.begin(), amount_keys.end());
+ rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys));
#ifdef DBG
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
#endif
@@ -782,7 +777,10 @@ namespace rct {
std::vector<uint64_t> batch_amounts(batch_size);
for (i = 0; i < batch_size; ++i)
batch_amounts[i] = outamounts[i + amounts_proved];
- rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts));
+ std::vector<key> keys(batch_size);
+ for (size_t j = 0; j < batch_size; ++j)
+ keys[j] = amount_keys[amounts_proved + j];
+ rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys));
#ifdef DBG
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
#endif
diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h
index de026226e..c6c21ad22 100644
--- a/src/ringct/rctTypes.h
+++ b/src/ringct/rctTypes.h
@@ -128,7 +128,7 @@ namespace rct {
key senderPk;
BEGIN_SERIALIZE_OBJECT()
- FIELD(mask)
+ FIELD(mask) // not saved from v2 BPs
FIELD(amount)
// FIELD(senderPk) // not serialized, as we do not use it in monero currently
END_SERIALIZE()
@@ -285,7 +285,6 @@ namespace rct {
if (type == RCTTypeBulletproof2)
{
ar.begin_object();
- FIELD_N("mask", ecdhInfo[i].mask);
if (!typename Archive<W>::is_saving())
memset(ecdhInfo[i].amount.bytes, 0, sizeof(ecdhInfo[i].amount.bytes));
crypto::hash8 &amount = (crypto::hash8&)ecdhInfo[i].amount;