ringct: thread verRct and verRctSimple

This commit is contained in:
moneromooo-monero 2016-10-15 13:31:16 +01:00
parent e06a4daf33
commit 3429bfb71d
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3

View File

@ -28,14 +28,26 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/asio.hpp>
#include "misc_log_ex.h" #include "misc_log_ex.h"
#include "common/perf_timer.h" #include "common/perf_timer.h"
#include "common/util.h"
#include "rctSigs.h" #include "rctSigs.h"
#include "cryptonote_core/cryptonote_format_utils.h" #include "cryptonote_core/cryptonote_format_utils.h"
using namespace crypto; using namespace crypto;
using namespace std; using namespace std;
#define KILL_IOSERVICE() \
if(ioservice_active) \
{ \
work.reset(); \
while (!ioservice.stopped()) ioservice.poll(); \
threadpool.join_all(); \
ioservice.stop(); \
ioservice_active = false; \
}
namespace rct { namespace rct {
//Schnorr Non-linkable //Schnorr Non-linkable
@ -348,6 +360,10 @@ namespace rct {
return true; return true;
} }
void verRangeWrapper(const key & C, const rangeSig & as, bool &result) {
result = verRange(C, as);
}
key get_pre_mlsag_hash(const rctSig &rv) key get_pre_mlsag_hash(const rctSig &rv)
{ {
keyV hashes; keyV hashes;
@ -528,6 +544,10 @@ namespace rct {
return MLSAG_Ver(message, M, mg, rows); return MLSAG_Ver(message, M, mg, rows);
} }
void verRctMGSimpleWrapper(const key &message, const mgSig &mg, const ctkeyV & pubs, const key & C, bool &result) {
result = verRctMGSimple(message, mg, pubs, C);
}
//These functions get keys from blockchain //These functions get keys from blockchain
//replace these when connecting blockchain //replace these when connecting blockchain
//getKeyFromBlockchain grabs a key from the blockchain at "reference_index" to mix with //getKeyFromBlockchain grabs a key from the blockchain at "reference_index" to mix with
@ -745,17 +765,41 @@ namespace rct {
// some rct ops can throw // some rct ops can throw
try try
{ {
size_t i = 0; boost::asio::io_service ioservice;
bool tmp; boost::thread_group threadpool;
std::unique_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(ioservice));
size_t threads = tools::get_max_concurrency();
threads = std::min(threads, rv.outPk.size());
for (size_t i = 0; i < threads; ++i)
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
bool ioservice_active = threads > 1;
std::deque<bool> results(rv.outPk.size(), false);
epee::misc_utils::auto_scope_leave_caller ioservice_killer = epee::misc_utils::create_scope_leave_handler([&]() { KILL_IOSERVICE(); });
DP("range proofs verified?"); DP("range proofs verified?");
for (i = 0; i < rv.outPk.size(); i++) { for (size_t i = 0; i < rv.outPk.size(); i++) {
tmp = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]); if (threads > 1) {
DP(tmp); ioservice.dispatch(boost::bind(&verRangeWrapper, std::cref(rv.outPk[i].mask), std::cref(rv.p.rangeSigs[i]), std::ref(results[i])));
if (!tmp) { }
LOG_ERROR("Range proof verification failed for input " << i); else {
return false; bool tmp = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]);
DP(tmp);
if (!tmp) {
LOG_ERROR("Range proof verification failed for input " << i);
return false;
}
} }
} }
KILL_IOSERVICE();
if (threads > 1) {
for (size_t i = 0; i < rv.outPk.size(); ++i) {
if (!results[i]) {
LOG_ERROR("Range proof verified failed for input " << i);
return false;
}
}
}
//compute txn fee //compute txn fee
key txnFeeKey = scalarmultH(d2h(rv.txnFee)); key txnFeeKey = scalarmultH(d2h(rv.txnFee));
bool mgVerd = verRctMG(rv.p.MGs[0], rv.mixRing, rv.outPk, txnFeeKey, get_pre_mlsag_hash(rv)); bool mgVerd = verRctMG(rv.p.MGs[0], rv.mixRing, rv.outPk, txnFeeKey, get_pre_mlsag_hash(rv));
@ -786,29 +830,87 @@ namespace rct {
CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.p.MGs.size(), false, "Mismatched sizes of rv.pseudoOuts and rv.p.MGs"); CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.p.MGs.size(), false, "Mismatched sizes of rv.pseudoOuts and rv.p.MGs");
CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing"); CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing");
key sumOutpks = identity(); {
for (i = 0; i < rv.outPk.size(); i++) { boost::asio::io_service ioservice;
if (!verRange(rv.outPk[i].mask, rv.p.rangeSigs[i])) { boost::thread_group threadpool;
std::unique_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(ioservice));
size_t threads = tools::get_max_concurrency();
threads = std::min(threads, rv.outPk.size());
for (size_t i = 0; i < threads; ++i)
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
bool ioservice_active = threads > 1;
std::deque<bool> results(rv.outPk.size(), false);
epee::misc_utils::auto_scope_leave_caller ioservice_killer = epee::misc_utils::create_scope_leave_handler([&]() { KILL_IOSERVICE(); });
for (i = 0; i < rv.outPk.size(); i++) {
if (threads > 1) {
ioservice.dispatch(boost::bind(&verRangeWrapper, std::cref(rv.outPk[i].mask), std::cref(rv.p.rangeSigs[i]), std::ref(results[i])));
}
else if (!verRange(rv.outPk[i].mask, rv.p.rangeSigs[i])) {
LOG_ERROR("Range proof verified failed for input " << i); LOG_ERROR("Range proof verified failed for input " << i);
return false; return false;
} }
}
KILL_IOSERVICE();
if (threads > 1) {
for (size_t i = 0; i < rv.outPk.size(); ++i) {
if (!results[i]) {
LOG_ERROR("Range proof verified failed for input " << i);
return false;
}
}
}
}
key sumOutpks = identity();
for (i = 0; i < rv.outPk.size(); i++) {
addKeys(sumOutpks, sumOutpks, rv.outPk[i].mask); addKeys(sumOutpks, sumOutpks, rv.outPk[i].mask);
} }
DP(sumOutpks); DP(sumOutpks);
key txnFeeKey = scalarmultH(d2h(rv.txnFee)); key txnFeeKey = scalarmultH(d2h(rv.txnFee));
addKeys(sumOutpks, txnFeeKey, sumOutpks); addKeys(sumOutpks, txnFeeKey, sumOutpks);
bool tmpb = false;
key message = get_pre_mlsag_hash(rv); key message = get_pre_mlsag_hash(rv);
key sumPseudoOuts = identity();
for (i = 0 ; i < rv.mixRing.size() ; i++) { {
tmpb = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], rv.pseudoOuts[i]); boost::asio::io_service ioservice;
addKeys(sumPseudoOuts, sumPseudoOuts, rv.pseudoOuts[i]); boost::thread_group threadpool;
DP(tmpb); std::unique_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(ioservice));
if (!tmpb) { size_t threads = tools::get_max_concurrency();
threads = std::min(threads, rv.mixRing.size());
for (size_t i = 0; i < threads; ++i)
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioservice));
bool ioservice_active = threads > 1;
std::deque<bool> results(rv.mixRing.size(), false);
epee::misc_utils::auto_scope_leave_caller ioservice_killer = epee::misc_utils::create_scope_leave_handler([&]() { KILL_IOSERVICE(); });
for (i = 0 ; i < rv.mixRing.size() ; i++) {
if (threads > 1) {
ioservice.dispatch(boost::bind(&verRctMGSimpleWrapper, std::cref(message), std::cref(rv.p.MGs[i]), std::cref(rv.mixRing[i]), std::cref(rv.pseudoOuts[i]), std::ref(results[i])));
}
else {
bool tmpb = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], rv.pseudoOuts[i]);
DP(tmpb);
if (!tmpb) {
LOG_ERROR("verRctMGSimple failed for input " << i);
return false;
}
}
}
KILL_IOSERVICE();
if (threads > 1) {
for (size_t i = 0; i < results.size(); ++i) {
if (!results[i]) {
LOG_ERROR("verRctMGSimple failed for input " << i); LOG_ERROR("verRctMGSimple failed for input " << i);
return false; return false;
}
} }
}
}
key sumPseudoOuts = identity();
for (i = 0 ; i < rv.mixRing.size() ; i++) {
addKeys(sumPseudoOuts, sumPseudoOuts, rv.pseudoOuts[i]);
} }
DP(sumPseudoOuts); DP(sumPseudoOuts);