aboutsummaryrefslogtreecommitdiff
path: root/src/ringct
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-01-18 12:01:45 +0000
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-09-11 13:37:31 +0000
commite895c3def1aa6c037c3d9c2daca8dacbd62e74dd (patch)
tree4c5281f1d9bfda0f0b6e8e2e504a49091204ffab /src/ringct
parentmultiexp: bos coster now works for just one point (diff)
downloadmonero-e895c3def1aa6c037c3d9c2daca8dacbd62e74dd.tar.xz
make straus cached mode thread safe, and add tests for it
Diffstat (limited to 'src/ringct')
-rw-r--r--src/ringct/bulletproofs.cc11
-rw-r--r--src/ringct/multiexp.cc80
-rw-r--r--src/ringct/multiexp.h7
3 files changed, 67 insertions, 31 deletions
diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc
index 1c29b1b99..6ba984b03 100644
--- a/src/ringct/bulletproofs.cc
+++ b/src/ringct/bulletproofs.cc
@@ -61,6 +61,7 @@ static constexpr size_t maxM = 16;
static rct::key Hi[maxN*maxM], Gi[maxN*maxM];
static ge_p3 Hi_p3[maxN*maxM], Gi_p3[maxN*maxM];
static ge_dsmp Gprecomp[maxN*maxM], Hprecomp[maxN*maxM];
+static std::shared_ptr<straus_cached_data> HiGi_cache;
static const rct::key TWO = { {0x02, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } };
static const rct::keyV oneN = vector_dup(rct::identity(), maxN);
static const rct::keyV twoN = vector_powers(TWO, maxN);
@@ -70,7 +71,7 @@ static boost::mutex init_mutex;
static inline rct::key multiexp(const std::vector<MultiexpData> &data, bool HiGi)
{
if (HiGi || data.size() < 1000)
- return straus(data, HiGi);
+ return straus(data, HiGi ? HiGi_cache: NULL);
else
return bos_coster_heap_conv_robust(data);
}
@@ -116,6 +117,7 @@ static void init_exponents()
static bool init_done = false;
if (init_done)
return;
+ std::vector<MultiexpData> data;
for (size_t i = 0; i < maxN*maxM; ++i)
{
Hi[i] = get_exponent(rct::H, i * 2);
@@ -124,8 +126,13 @@ static void init_exponents()
Gi[i] = get_exponent(rct::H, i * 2 + 1);
rct::precomp(Gprecomp[i], Gi[i]);
CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Gi_p3[i], Gi[i].bytes) == 0, "ge_frombytes_vartime failed");
+
+ data.push_back({rct::zero(), Gi[i]});
+ data.push_back({rct::zero(), Hi[i]});
}
- MINFO("cache size: " << (sizeof(Hi)+sizeof(Hprecomp)+sizeof(Hi_p3))*2/1024 << " kB");
+ HiGi_cache = straus_init_cache(data);
+ size_t cache_size = (sizeof(Hi)+sizeof(Hprecomp)+sizeof(Hi_p3))*2 + straus_get_cache_size(HiGi_cache);
+ MINFO("cache size: " << cache_size/1024 << " kB");
init_done = true;
}
diff --git a/src/ringct/multiexp.cc b/src/ringct/multiexp.cc
index 7ed9672f2..4f16bd588 100644
--- a/src/ringct/multiexp.cc
+++ b/src/ringct/multiexp.cc
@@ -259,42 +259,66 @@ rct::key bos_coster_heap_conv_robust(std::vector<MultiexpData> data)
return res;
}
-rct::key straus(const std::vector<MultiexpData> &data, bool HiGi)
+struct straus_cached_data
{
- MULTIEXP_PERF(PERF_TIMER_UNIT(straus, 1000000));
+ std::vector<std::vector<ge_cached>> multiples;
+};
- MULTIEXP_PERF(PERF_TIMER_START_UNIT(setup, 1000000));
- static constexpr unsigned int c = 4;
- static constexpr unsigned int mask = (1<<c)-1;
- static std::vector<std::vector<ge_cached>> HiGi_multiples;
- std::vector<std::vector<ge_cached>> local_multiples, &multiples = HiGi ? HiGi_multiples : local_multiples;
+static constexpr unsigned int STRAUS_C = 4;
+
+std::shared_ptr<straus_cached_data> straus_init_cache(const std::vector<MultiexpData> &data)
+{
+ MULTIEXP_PERF(PERF_TIMER_START_UNIT(multiples, 1000000));
ge_cached cached;
ge_p1p1 p1;
ge_p3 p3;
+ std::shared_ptr<straus_cached_data> cache(new straus_cached_data());
- std::vector<uint8_t> skip(data.size());
- for (size_t i = 0; i < data.size(); ++i)
- skip[i] = data[i].scalar == rct::zero() || !memcmp(&data[i].point, &ge_p3_identity, sizeof(ge_p3));
-
- MULTIEXP_PERF(PERF_TIMER_START_UNIT(multiples, 1000000));
- multiples.resize(1<<c);
- size_t offset = multiples[1].size();
- multiples[1].resize(std::max(offset, data.size()));
+ cache->multiples.resize(1<<STRAUS_C);
+ size_t offset = cache->multiples[1].size();
+ cache->multiples[1].resize(std::max(offset, data.size()));
for (size_t i = offset; i < data.size(); ++i)
- ge_p3_to_cached(&multiples[1][i], &data[i].point);
- for (size_t i=2;i<1<<c;++i)
- multiples[i].resize(std::max(offset, data.size()));
+ ge_p3_to_cached(&cache->multiples[1][i], &data[i].point);
+ for (size_t i=2;i<1<<STRAUS_C;++i)
+ cache->multiples[i].resize(std::max(offset, data.size()));
for (size_t j=offset;j<data.size();++j)
{
- for (size_t i=2;i<1<<c;++i)
+ for (size_t i=2;i<1<<STRAUS_C;++i)
{
- ge_add(&p1, &data[j].point, &multiples[i-1][j]);
+ ge_add(&p1, &data[j].point, &cache->multiples[i-1][j]);
ge_p1p1_to_p3(&p3, &p1);
- ge_p3_to_cached(&multiples[i][j], &p3);
+ ge_p3_to_cached(&cache->multiples[i][j], &p3);
}
}
MULTIEXP_PERF(PERF_TIMER_STOP(multiples));
+ return cache;
+}
+
+size_t straus_get_cache_size(const std::shared_ptr<straus_cached_data> &cache)
+{
+ size_t sz = 0;
+ for (const auto &e0: cache->multiples)
+ sz += e0.size() * sizeof(ge_p3);
+ return sz;
+}
+
+rct::key straus(const std::vector<MultiexpData> &data, const std::shared_ptr<straus_cached_data> &cache)
+{
+ MULTIEXP_PERF(PERF_TIMER_UNIT(straus, 1000000));
+ bool HiGi = cache != NULL;
+
+ MULTIEXP_PERF(PERF_TIMER_START_UNIT(setup, 1000000));
+ static constexpr unsigned int mask = (1<<STRAUS_C)-1;
+ std::shared_ptr<straus_cached_data> local_cache = cache == NULL ? straus_init_cache(data) : cache;
+ ge_cached cached;
+ ge_p1p1 p1;
+ ge_p3 p3;
+
+ std::vector<uint8_t> skip(data.size());
+ for (size_t i = 0; i < data.size(); ++i)
+ skip[i] = data[i].scalar == rct::zero() || !memcmp(&data[i].point, &ge_p3_identity, sizeof(ge_p3));
+
MULTIEXP_PERF(PERF_TIMER_START_UNIT(digits, 1000000));
std::vector<std::vector<uint8_t>> digits;
digits.resize(data.size());
@@ -305,7 +329,7 @@ rct::key straus(const std::vector<MultiexpData> &data, bool HiGi)
memcpy(bytes33, data[j].scalar.bytes, 32);
bytes33[32] = 0;
#if 1
- static_assert(c == 4, "optimized version needs c == 4");
+ static_assert(STRAUS_C == 4, "optimized version needs STRAUS_C == 4");
const unsigned char *bytes = bytes33;
unsigned int i;
for (i = 0; i < 256; i += 8, bytes++)
@@ -339,22 +363,22 @@ rct::key straus(const std::vector<MultiexpData> &data, bool HiGi)
maxscalar = data[i].scalar;
size_t i = 0;
while (i < 256 && !(maxscalar < pow2(i)))
- i += c;
+ i += STRAUS_C;
MULTIEXP_PERF(PERF_TIMER_STOP(setup));
ge_p3 res_p3 = ge_p3_identity;
- if (!(i < c))
+ if (!(i < STRAUS_C))
goto skipfirst;
- while (!(i < c))
+ while (!(i < STRAUS_C))
{
- for (size_t j = 0; j < c; ++j)
+ for (size_t j = 0; j < STRAUS_C; ++j)
{
ge_p3_to_cached(&cached, &res_p3);
ge_add(&p1, &res_p3, &cached);
ge_p1p1_to_p3(&res_p3, &p1);
}
skipfirst:
- i -= c;
+ i -= STRAUS_C;
for (size_t j = 0; j < data.size(); ++j)
{
if (skip[j])
@@ -362,7 +386,7 @@ skipfirst:
int digit = digits[j][i];
if (digit)
{
- ge_add(&p1, &res_p3, &multiples[digit][j]);
+ ge_add(&p1, &res_p3, &local_cache->multiples[digit][j]);
ge_p1p1_to_p3(&res_p3, &p1);
}
}
diff --git a/src/ringct/multiexp.h b/src/ringct/multiexp.h
index cc53e633e..44998e2e0 100644
--- a/src/ringct/multiexp.h
+++ b/src/ringct/multiexp.h
@@ -36,6 +36,7 @@
#include <vector>
#include "crypto/crypto.h"
#include "rctTypes.h"
+#include "misc_log_ex.h"
namespace rct
{
@@ -52,9 +53,13 @@ struct MultiexpData {
}
};
+struct straus_cached_data;
+
rct::key bos_coster_heap_conv(std::vector<MultiexpData> data);
rct::key bos_coster_heap_conv_robust(std::vector<MultiexpData> data);
-rct::key straus(const std::vector<MultiexpData> &data, bool HiGi = false);
+std::shared_ptr<straus_cached_data> straus_init_cache(const std::vector<MultiexpData> &data);
+size_t straus_get_cache_size(const std::shared_ptr<straus_cached_data> &cache);
+rct::key straus(const std::vector<MultiexpData> &data, const std::shared_ptr<straus_cached_data> &cache = NULL);
}