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-01-22 23:17:39 +0000
commit7d375981584e5ddac4ea6ad8879e2211d465b79d (patch)
tree82341e77219309514ab8bc12d6c3bd65b60a2293 /src/ringct
parentringct: encode 8 byte amount, saving 24 bytes per output (diff)
downloadmonero-7d375981584e5ddac4ea6ad8879e2211d465b79d.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.cpp13
-rw-r--r--src/ringct/rctTypes.h3
4 files changed, 51 insertions, 26 deletions
diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp
index b28aa4fe6..e39ba16fd 100644
--- a/src/ringct/rctOps.cpp
+++ b/src/ringct/rctOps.cpp
@@ -672,36 +672,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 6687c91cd..81bec487c 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -79,9 +79,12 @@ namespace
}
namespace rct {
- Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts)
+ Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk)
{
- 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;
@@ -803,7 +806,8 @@ namespace rct {
}
else
{
- rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts));
+ const epee::span<const key> keys{&amount_keys[0], amount_keys.size()};
+ 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
@@ -831,7 +835,8 @@ namespace rct {
}
else
{
- rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts));
+ const epee::span<const key> keys{&amount_keys[amounts_proved], batch_size};
+ 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 54fca1d05..a02c338e9 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()
@@ -286,7 +286,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;