aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--Dockerfile30
-rw-r--r--cmake/GenVersion.cmake4
-rw-r--r--src/crypto/crypto.cpp15
-rw-r--r--src/crypto/crypto.h1
-rw-r--r--src/crypto/random.c15
-rw-r--r--src/crypto/random.h1
-rw-r--r--src/device/device_ledger.cpp4
-rw-r--r--src/device/device_ledger.hpp2
-rw-r--r--src/ringct/bulletproofs.cc5
-rw-r--r--src/ringct/rctOps.cpp46
-rw-r--r--src/ringct/rctOps.h5
-rw-r--r--src/ringct/rctSigs.cpp75
-rw-r--r--src/rpc/core_rpc_server.cpp1
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h4
-rw-r--r--src/simplewallet/simplewallet.cpp65
-rw-r--r--src/simplewallet/simplewallet.h1
-rw-r--r--src/version.cpp.in2
-rw-r--r--src/version.h1
-rw-r--r--src/wallet/wallet2.cpp140
-rw-r--r--src/wallet/wallet2.h12
-rw-r--r--src/wallet/wallet_rpc_server.cpp2
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h4
-rw-r--r--tests/performance_tests/main.cpp20
-rw-r--r--tests/performance_tests/rct_mlsag.h12
-rw-r--r--tests/unit_tests/ringct.cpp15
-rw-r--r--utils/build_scripts/android32.Dockerfile2
-rw-r--r--utils/build_scripts/android64.Dockerfile2
28 files changed, 325 insertions, 163 deletions
diff --git a/.travis.yml b/.travis.yml
index 07b92aaff..516e4f8e5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -51,7 +51,7 @@ before_script:
- if [ -n "$OSX_SDK" -a -f contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C contrib/depends/SDKs -xf contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
- if [[ $HOST = *-mingw32 ]]; then $DOCKER_EXEC bash -c "update-alternatives --set $HOST-g++ \$(which $HOST-g++-posix)"; fi
- if [[ $HOST = *-mingw32 ]]; then $DOCKER_EXEC bash -c "update-alternatives --set $HOST-gcc \$(which $HOST-gcc-posix)"; fi
- - if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC bash -c "CONFIG_SHELL= make $MAKEJOBS -C contrib/depends HOST=$HOST $DEP_OPTS"; fi
+ - if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC bash -c "make $MAKEJOBS -C contrib/depends HOST=$HOST $DEP_OPTS"; fi
script:
- git submodule init && git submodule update
- export TRAVIS_COMMIT_LOG=`git log --format=fuller -1`
diff --git a/Dockerfile b/Dockerfile
index 999290c95..a6fab3823 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -29,9 +29,9 @@ ENV CFLAGS='-fPIC'
ENV CXXFLAGS='-fPIC'
#Cmake
-ARG CMAKE_VERSION=3.14.0
+ARG CMAKE_VERSION=3.14.6
ARG CMAKE_VERSION_DOT=v3.14
-ARG CMAKE_HASH=aa76ba67b3c2af1946701f847073f4652af5cbd9f141f221c97af99127e75502
+ARG CMAKE_HASH=4e8ea11cabe459308671b476469eace1622e770317a15951d7b55a82ccaaccb9
RUN set -ex \
&& curl -s -O https://cmake.org/files/${CMAKE_VERSION_DOT}/cmake-${CMAKE_VERSION}.tar.gz \
&& echo "${CMAKE_HASH} cmake-${CMAKE_VERSION}.tar.gz" | sha256sum -c \
@@ -42,9 +42,9 @@ RUN set -ex \
&& make install
## Boost
-ARG BOOST_VERSION=1_69_0
-ARG BOOST_VERSION_DOT=1.69.0
-ARG BOOST_HASH=8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406
+ARG BOOST_VERSION=1_70_0
+ARG BOOST_VERSION_DOT=1.70.0
+ARG BOOST_HASH=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778
RUN set -ex \
&& curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
&& echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \
@@ -69,8 +69,8 @@ RUN set -ex \
ENV OPENSSL_ROOT_DIR=/usr/local/openssl-${OPENSSL_VERSION}
# ZMQ
-ARG ZMQ_VERSION=v4.3.1
-ARG ZMQ_HASH=2cb1240db64ce1ea299e00474c646a2453a8435b
+ARG ZMQ_VERSION=v4.3.2
+ARG ZMQ_HASH=a84ffa12b2eb3569ced199660bac5ad128bff1f0
RUN set -ex \
&& git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \
&& cd libzmq \
@@ -82,8 +82,8 @@ RUN set -ex \
&& ldconfig
# zmq.hpp
-ARG CPPZMQ_VERSION=v4.3.0
-ARG CPPZMQ_HASH=213da0b04ae3b4d846c9abc46bab87f86bfb9cf4
+ARG CPPZMQ_VERSION=v4.4.1
+ARG CPPZMQ_HASH=f5b36e563598d48fcc0d82e589d3596afef945ae
RUN set -ex \
&& git clone https://github.com/zeromq/cppzmq.git -b ${CPPZMQ_VERSION} \
&& cd cppzmq \
@@ -103,8 +103,8 @@ RUN set -ex \
&& make install
# Sodium
-ARG SODIUM_VERSION=1.0.17
-ARG SODIUM_HASH=b732443c442239c2e0184820e9b23cca0de0828c
+ARG SODIUM_VERSION=1.0.18
+ARG SODIUM_HASH=4f5e89fa84ce1d178a6765b8b46f2b6f91216677
RUN set -ex \
&& git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} \
&& cd libsodium \
@@ -116,8 +116,8 @@ RUN set -ex \
&& make install
# Udev
-ARG UDEV_VERSION=v3.2.7
-ARG UDEV_HASH=4758e346a14126fc3a964de5831e411c27ebe487
+ARG UDEV_VERSION=v3.2.8
+ARG UDEV_HASH=d69f3f28348123ab7fa0ebac63ec2fd16800c5e0
RUN set -ex \
&& git clone https://github.com/gentoo/eudev -b ${UDEV_VERSION} \
&& cd eudev \
@@ -152,8 +152,8 @@ RUN set -ex \
&& make install
# Protobuf
-ARG PROTOBUF_VERSION=v3.7.0
-ARG PROTOBUF_HASH=582743bf40c5d3639a70f98f183914a2c0cd0680
+ARG PROTOBUF_VERSION=v3.7.1
+ARG PROTOBUF_HASH=6973c3a5041636c1d8dc5f7f6c8c1f3c15bc63d6
RUN set -ex \
&& git clone https://github.com/protocolbuffers/protobuf -b ${PROTOBUF_VERSION} \
&& cd protobuf \
diff --git a/cmake/GenVersion.cmake b/cmake/GenVersion.cmake
index b2ccfbc34..992539507 100644
--- a/cmake/GenVersion.cmake
+++ b/cmake/GenVersion.cmake
@@ -36,6 +36,7 @@ if(RET)
message(WARNING "Cannot determine current commit. Make sure that you are building either from a Git working tree or from a source archive.")
set(VERSIONTAG "unknown")
+ set(VERSION_IS_RELEASE "false")
configure_file("src/version.cpp.in" "${TO}")
else()
string(SUBSTRING ${COMMIT} 0 9 COMMIT)
@@ -47,6 +48,7 @@ else()
if(NOT TAGGEDCOMMIT)
message(WARNING "Cannot determine most recent tag. Make sure that you are building either from a Git working tree or from a source archive.")
set(VERSIONTAG "${COMMIT}")
+ set(VERSION_IS_RELEASE "false")
else()
message(STATUS "The most recent tag was at ${TAGGEDCOMMIT}")
@@ -54,9 +56,11 @@ else()
if(COMMIT STREQUAL TAGGEDCOMMIT)
message(STATUS "You are building a tagged release")
set(VERSIONTAG "release")
+ set(VERSION_IS_RELEASE "true")
else()
message(STATUS "You are ahead of or behind a tagged release")
set(VERSIONTAG "${COMMIT}")
+ set(VERSION_IS_RELEASE "false")
endif()
endif()
diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp
index d4b2a22bc..0ec992de9 100644
--- a/src/crypto/crypto.cpp
+++ b/src/crypto/crypto.cpp
@@ -88,13 +88,24 @@ namespace crypto {
return &reinterpret_cast<const unsigned char &>(scalar);
}
- void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes)
+ boost::mutex &get_random_lock()
{
static boost::mutex random_lock;
- boost::lock_guard<boost::mutex> lock(random_lock);
+ return random_lock;
+ }
+
+ void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes)
+ {
+ boost::lock_guard<boost::mutex> lock(get_random_lock());
generate_random_bytes_not_thread_safe(N, bytes);
}
+ void add_extra_entropy_thread_safe(const void *ptr, size_t bytes)
+ {
+ boost::lock_guard<boost::mutex> lock(get_random_lock());
+ add_extra_entropy_not_thread_safe(ptr, bytes);
+ }
+
static inline bool less32(const unsigned char *k0, const unsigned char *k1)
{
for (int n = 31; n >= 0; --n)
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index bac456f60..8ce321f71 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -147,6 +147,7 @@ namespace crypto {
};
void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes);
+ void add_extra_entropy_thread_safe(const void *ptr, size_t bytes);
/* Generate N random bytes
*/
diff --git a/src/crypto/random.c b/src/crypto/random.c
index 74b202661..766b5f558 100644
--- a/src/crypto/random.c
+++ b/src/crypto/random.c
@@ -146,3 +146,18 @@ void generate_random_bytes_not_thread_safe(size_t n, void *result) {
}
}
}
+
+void add_extra_entropy_not_thread_safe(const void *ptr, size_t bytes)
+{
+ size_t i;
+
+ while (bytes > 0)
+ {
+ hash_permutation(&state);
+ const size_t round_bytes = bytes > HASH_DATA_AREA ? HASH_DATA_AREA : bytes;
+ for (i = 0; i < round_bytes; ++i)
+ state.b[i] ^= ((const uint8_t*)ptr)[i];
+ bytes -= round_bytes;
+ ptr = cpadd(ptr, round_bytes);
+ }
+}
diff --git a/src/crypto/random.h b/src/crypto/random.h
index ccb9f4853..21a66d776 100644
--- a/src/crypto/random.h
+++ b/src/crypto/random.h
@@ -33,3 +33,4 @@
#include <stddef.h>
void generate_random_bytes_not_thread_safe(size_t n, void *result);
+void add_extra_entropy_not_thread_safe(const void *ptr, size_t bytes);
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index eba633da8..2d91b881b 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -320,7 +320,9 @@ namespace hw {
bool device_ledger::reset() {
reset_buffer();
int offset = set_command_header_noopt(INS_RESET);
- memmove(this->buffer_send+offset, MONERO_VERSION, strlen(MONERO_VERSION));
+ const size_t verlen = strlen(MONERO_VERSION);
+ ASSERT_X(offset + verlen <= BUFFER_SEND_SIZE, "MONERO_VERSION is too long")
+ memmove(this->buffer_send+offset, MONERO_VERSION, verlen);
offset += strlen(MONERO_VERSION);
this->buffer_send[4] = offset-5;
this->length_send = offset;
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index fe9028733..986087128 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -76,7 +76,7 @@ namespace hw {
rct::key AKout;
ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, bool is_subaddress, bool is_change_address, size_t index, const rct::key& P,const rct::key& AK);
ABPkeys(const ABPkeys& keys) ;
- ABPkeys() {index=0;is_subaddress=false;is_subaddress=false;is_change_address=false;}
+ ABPkeys() {index=0;is_subaddress=false;is_change_address=false;additional_key=false;}
ABPkeys &operator=(const ABPkeys &keys);
};
diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc
index 6270d4d14..ff6fee95c 100644
--- a/src/ringct/bulletproofs.cc
+++ b/src/ringct/bulletproofs.cc
@@ -101,7 +101,10 @@ static rct::key get_exponent(const rct::key &base, size_t idx)
{
static const std::string salt("bulletproof");
std::string hashed = std::string((const char*)base.bytes, sizeof(base)) + salt + tools::get_varint_data(idx);
- const rct::key e = rct::hashToPoint(rct::hash2rct(crypto::cn_fast_hash(hashed.data(), hashed.size())));
+ rct::key e;
+ ge_p3 e_p3;
+ rct::hash_to_p3(e_p3, rct::hash2rct(crypto::cn_fast_hash(hashed.data(), hashed.size())));
+ ge_p3_tobytes(e.bytes, &e_p3);
CHECK_AND_ASSERT_THROW_MES(!(e == rct::identity()), "Exponent is point at infinity");
return e;
}
diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp
index b5499262f..6e4d063df 100644
--- a/src/ringct/rctOps.cpp
+++ b/src/ringct/rctOps.cpp
@@ -620,44 +620,16 @@ namespace rct {
sc_reduce32(rv.bytes);
return rv;
}
-
- key hashToPointSimple(const key & hh) {
- key pointk;
- ge_p1p1 point2;
- ge_p2 point;
- ge_p3 res;
- key h = cn_fast_hash(hh);
- CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&res, h.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
- ge_p3_to_p2(&point, &res);
- ge_mul8(&point2, &point);
- ge_p1p1_to_p3(&res, &point2);
- ge_p3_tobytes(pointk.bytes, &res);
- return pointk;
- }
- key hashToPoint(const key & hh) {
- key pointk;
- ge_p2 point;
- ge_p1p1 point2;
- ge_p3 res;
- key h = cn_fast_hash(hh);
- ge_fromfe_frombytes_vartime(&point, h.bytes);
- ge_mul8(&point2, &point);
- ge_p1p1_to_p3(&res, &point2);
- ge_p3_tobytes(pointk.bytes, &res);
- return pointk;
- }
-
- void hashToPoint(key & pointk, const key & hh) {
- ge_p2 point;
- ge_p1p1 point2;
- ge_p3 res;
- key h = cn_fast_hash(hh);
- ge_fromfe_frombytes_vartime(&point, h.bytes);
- ge_mul8(&point2, &point);
- ge_p1p1_to_p3(&res, &point2);
- ge_p3_tobytes(pointk.bytes, &res);
- }
+ // Hash a key to p3 representation
+ void hash_to_p3(ge_p3 &hash8_p3, const key &k) {
+ key hash_key = cn_fast_hash(k);
+ ge_p2 hash_p2;
+ ge_fromfe_frombytes_vartime(&hash_p2, hash_key.bytes);
+ ge_p1p1 hash8_p1p1;
+ ge_mul8(&hash8_p1p1, &hash_p2);
+ ge_p1p1_to_p3(&hash8_p3, &hash8_p1p1);
+ }
//sums a vector of curve points (for scalars use sc_add)
void sumKeys(key & Csum, const keyV & Cis) {
diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h
index dd6d87593..c24d48e9a 100644
--- a/src/ringct/rctOps.h
+++ b/src/ringct/rctOps.h
@@ -172,10 +172,7 @@ namespace rct {
key cn_fast_hash(const key64 keys);
key hash_to_scalar(const key64 keys);
- //returns hashToPoint as described in https://github.com/ShenNoether/ge_fromfe_writeup
- key hashToPointSimple(const key &in);
- key hashToPoint(const key &in);
- void hashToPoint(key &out, const key &in);
+ void hash_to_p3(ge_p3 &hash8_p3, const key &k);
//sums a vector of curve points (for scalars use sc_add)
void sumKeys(key & Csum, const key &Cis);
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index ff2a81d43..a7b265d63 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -163,14 +163,11 @@ namespace rct {
return verifyBorromean(bb, P1_p3, P2_p3);
}
- //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
- //This is a just slghtly more efficient version than the ones described below
- //(will be explained in more detail in Ring Multisig paper
- //These are aka MG signatutes in earlier drafts of the ring ct paper
- // c.f. https://eprint.iacr.org/2015/1098 section 2.
- // Gen creates a signature which proves that for some column in the keymatrix "pk"
- // the signer knows a secret key for each row in that column
- // Ver verifies that the MG sig was created correctly
+ // MLSAG signatures
+ // See paper by Noether (https://eprint.iacr.org/2015/1098)
+ // This generalization allows for some dimensions not to require linkability;
+ // this is used in practice for commitment data within signatures
+ // Note that using more than one linkable dimension is not recommended.
mgSig MLSAG_Gen(const key &message, const keyM & pk, const keyV & xx, const multisig_kLRki *kLRki, key *mscout, const unsigned int index, size_t dsRows, hw::device &hwdev) {
mgSig rv;
size_t cols = pk.size();
@@ -188,6 +185,7 @@ namespace rct {
size_t i = 0, j = 0, ii = 0;
key c, c_old, L, R, Hi;
+ ge_p3 Hi_p3;
sc_0(c_old.bytes);
vector<geDsmp> Ip(dsRows);
rv.II = keyV(dsRows);
@@ -208,7 +206,8 @@ namespace rct {
rv.II[i] = kLRki->ki;
}
else {
- Hi = hashToPoint(pk[index][i]);
+ hash_to_p3(Hi_p3, pk[index][i]);
+ ge_p3_tobytes(Hi.bytes, &Hi_p3);
hwdev.mlsag_prepare(Hi, xx[i], alpha[i] , aG[i] , aHP[i] , rv.II[i]);
toHash[3 * i + 2] = aG[i];
toHash[3 * i + 3] = aHP[i];
@@ -235,7 +234,8 @@ namespace rct {
sc_0(c.bytes);
for (j = 0; j < dsRows; j++) {
addKeys2(L, rv.ss[i][j], c_old, pk[i][j]);
- hashToPoint(Hi, pk[i][j]);
+ hash_to_p3(Hi_p3, pk[i][j]);
+ ge_p3_tobytes(Hi.bytes, &Hi_p3);
addKeys3(R, rv.ss[i][j], Hi, c_old, Ip[j].k);
toHash[3 * j + 1] = pk[i][j];
toHash[3 * j + 2] = L;
@@ -260,43 +260,42 @@ namespace rct {
return rv;
}
- //Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
- //This is a just slghtly more efficient version than the ones described below
- //(will be explained in more detail in Ring Multisig paper
- //These are aka MG signatutes in earlier drafts of the ring ct paper
- // c.f. https://eprint.iacr.org/2015/1098 section 2.
- // Gen creates a signature which proves that for some column in the keymatrix "pk"
- // the signer knows a secret key for each row in that column
- // Ver verifies that the MG sig was created correctly
+ // MLSAG signatures
+ // See paper by Noether (https://eprint.iacr.org/2015/1098)
+ // This generalization allows for some dimensions not to require linkability;
+ // this is used in practice for commitment data within signatures
+ // Note that using more than one linkable dimension is not recommended.
bool MLSAG_Ver(const key &message, const keyM & pk, const mgSig & rv, size_t dsRows) {
-
size_t cols = pk.size();
- CHECK_AND_ASSERT_MES(cols >= 2, false, "Error! What is c if cols = 1!");
+ CHECK_AND_ASSERT_MES(cols >= 2, false, "Signature must contain more than one public key");
size_t rows = pk[0].size();
- CHECK_AND_ASSERT_MES(rows >= 1, false, "Empty pk");
+ CHECK_AND_ASSERT_MES(rows >= 1, false, "Bad total row number");
for (size_t i = 1; i < cols; ++i) {
- CHECK_AND_ASSERT_MES(pk[i].size() == rows, false, "pk is not rectangular");
+ CHECK_AND_ASSERT_MES(pk[i].size() == rows, false, "Bad public key matrix dimensions");
}
- CHECK_AND_ASSERT_MES(rv.II.size() == dsRows, false, "Bad II size");
- CHECK_AND_ASSERT_MES(rv.ss.size() == cols, false, "Bad rv.ss size");
+ CHECK_AND_ASSERT_MES(rv.II.size() == dsRows, false, "Wrong number of key images present");
+ CHECK_AND_ASSERT_MES(rv.ss.size() == cols, false, "Bad scalar matrix dimensions");
for (size_t i = 0; i < cols; ++i) {
- CHECK_AND_ASSERT_MES(rv.ss[i].size() == rows, false, "rv.ss is not rectangular");
+ CHECK_AND_ASSERT_MES(rv.ss[i].size() == rows, false, "Bad scalar matrix dimensions");
}
- CHECK_AND_ASSERT_MES(dsRows <= rows, false, "Bad dsRows value");
+ CHECK_AND_ASSERT_MES(dsRows <= rows, false, "Non-double-spend rows cannot exceed total rows");
- for (size_t i = 0; i < rv.ss.size(); ++i)
- for (size_t j = 0; j < rv.ss[i].size(); ++j)
- CHECK_AND_ASSERT_MES(sc_check(rv.ss[i][j].bytes) == 0, false, "Bad ss slot");
- CHECK_AND_ASSERT_MES(sc_check(rv.cc.bytes) == 0, false, "Bad cc");
+ for (size_t i = 0; i < rv.ss.size(); ++i) {
+ for (size_t j = 0; j < rv.ss[i].size(); ++j) {
+ CHECK_AND_ASSERT_MES(sc_check(rv.ss[i][j].bytes) == 0, false, "Bad signature scalar");
+ }
+ }
+ CHECK_AND_ASSERT_MES(sc_check(rv.cc.bytes) == 0, false, "Bad initial signature hash");
size_t i = 0, j = 0, ii = 0;
- key c, L, R, Hi;
+ key c, L, R;
key c_old = copy(rv.cc);
vector<geDsmp> Ip(dsRows);
for (i = 0 ; i < dsRows ; i++) {
+ CHECK_AND_ASSERT_MES(!(rv.II[i] == rct::identity()), false, "Bad key image");
precomp(Ip[i].k, rv.II[i]);
}
- size_t ndsRows = 3 * dsRows; //non Double Spendable Rows (see identity chains paper
+ size_t ndsRows = 3 * dsRows; // number of dimensions not requiring linkability
keyV toHash(1 + 3 * dsRows + 2 * (rows - dsRows));
toHash[0] = message;
i = 0;
@@ -304,9 +303,14 @@ namespace rct {
sc_0(c.bytes);
for (j = 0; j < dsRows; j++) {
addKeys2(L, rv.ss[i][j], c_old, pk[i][j]);
- hashToPoint(Hi, pk[i][j]);
- CHECK_AND_ASSERT_MES(!(Hi == rct::identity()), false, "Data hashed to point at infinity");
- addKeys3(R, rv.ss[i][j], Hi, c_old, Ip[j].k);
+
+ // Compute R directly
+ ge_p3 hash8_p3;
+ hash_to_p3(hash8_p3, pk[i][j]);
+ ge_p2 R_p2;
+ ge_double_scalarmult_precomp_vartime(&R_p2, rv.ss[i][j].bytes, &hash8_p3, c_old.bytes, Ip[j].k);
+ ge_tobytes(R.bytes, &R_p2);
+
toHash[3 * j + 1] = pk[i][j];
toHash[3 * j + 2] = L;
toHash[3 * j + 3] = R;
@@ -317,6 +321,7 @@ namespace rct {
toHash[ndsRows + 2 * ii + 2] = L;
}
c = hash_to_scalar(toHash);
+ CHECK_AND_ASSERT_MES(!(c == rct::zero()), false, "Bad signature hash");
copy(c_old, c);
i = (i + 1);
}
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 73138686d..1fc4b816f 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -2147,6 +2147,7 @@ namespace cryptonote
return r;
res.version = CORE_RPC_VERSION;
+ res.release = MONERO_VERSION_IS_RELEASE;
res.status = CORE_RPC_STATUS_OK;
return true;
}
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index aed967efb..325ac4343 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -87,7 +87,7 @@ namespace cryptonote
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 2
-#define CORE_RPC_VERSION_MINOR 9
+#define CORE_RPC_VERSION_MINOR 10
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
@@ -2053,11 +2053,13 @@ namespace cryptonote
{
std::string status;
uint32_t version;
+ bool release;
bool untrusted;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
KV_SERIALIZE(version)
+ KV_SERIALIZE(release)
KV_SERIALIZE(untrusted)
END_KV_SERIALIZE_MAP()
};
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 5d7321e48..9c3dc2b32 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -1254,7 +1254,7 @@ bool simple_wallet::export_multisig_main(const std::vector<std::string> &args, b
}
else
{
- bool r = epee::file_io_utils::save_string_to_file(filename, ciphertext);
+ bool r = m_wallet->save_to_file(filename, ciphertext);
if (!r)
{
fail_msg_writer() << tr("failed to save file ") << filename;
@@ -1315,7 +1315,7 @@ bool simple_wallet::import_multisig_main(const std::vector<std::string> &args, b
{
const std::string &filename = args[n];
std::string data;
- bool r = epee::file_io_utils::load_file_to_string(filename, data);
+ bool r = m_wallet->load_from_file(filename, data);
if (!r)
{
fail_msg_writer() << tr("failed to read file ") << filename;
@@ -1626,7 +1626,7 @@ bool simple_wallet::export_raw_multisig(const std::vector<std::string> &args)
if (!filenames.empty())
filenames += ", ";
filenames += filename;
- if (!epee::file_io_utils::save_string_to_file(filename, cryptonote::tx_to_blob(ptx.tx)))
+ if (!m_wallet->save_to_file(filename, cryptonote::tx_to_blob(ptx.tx)))
{
fail_msg_writer() << tr("Failed to export multisig transaction to file ") << filename;
return true;
@@ -2712,6 +2712,35 @@ bool simple_wallet::set_device_name(const std::vector<std::string> &args/* = std
return true;
}
+bool simple_wallet::set_export_format(const std::vector<std::string> &args/* = std::vector<std::string()*/)
+{
+ if (args.size() < 2)
+ {
+ fail_msg_writer() << tr("Export format not specified");
+ return true;
+ }
+
+ if (boost::algorithm::iequals(args[1], "ascii"))
+ {
+ m_wallet->set_export_format(tools::wallet2::ExportFormat::Ascii);
+ }
+ else if (boost::algorithm::iequals(args[1], "binary"))
+ {
+ m_wallet->set_export_format(tools::wallet2::ExportFormat::Binary);
+ }
+ else
+ {
+ fail_msg_writer() << tr("Export format not recognized.");
+ return true;
+ }
+ const auto pwd_container = get_and_verify_password();
+ if (pwd_container)
+ {
+ m_wallet->rewrite(m_wallet_file, pwd_container->password());
+ }
+ return true;
+}
+
bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
if(args.empty())
@@ -2912,7 +2941,9 @@ simple_wallet::simple_wallet()
"setup-background-mining <1|0>\n "
" Whether to enable background mining. Set this to support the network and to get a chance to receive new monero.\n "
"device-name <device_name[:device_spec]>\n "
- " Device name for hardware wallet."));
+ " Device name for hardware wallet.\n "
+ "export-format <\"binary\"|\"ascii\">\n "
+ " Save all exported files as binary (cannot be copied and pasted) or ascii (can be).\n "));
m_cmd_binder.set_handler("encrypted_seed",
boost::bind(&simple_wallet::encrypted_seed, this, _1),
tr("Display the encrypted Electrum-style mnemonic seed."));
@@ -3278,6 +3309,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
success_msg_writer() << "track-uses = " << m_wallet->track_uses();
success_msg_writer() << "setup-background-mining = " << setup_background_mining_string;
success_msg_writer() << "device-name = " << m_wallet->device_name();
+ success_msg_writer() << "export-format = " << (m_wallet->export_format() == tools::wallet2::ExportFormat::Ascii ? "ascii" : "binary");
return true;
}
else
@@ -3336,6 +3368,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("track-uses", set_track_uses, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("setup-background-mining", set_setup_background_mining, tr("1/yes or 0/no"));
CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("<device_name[:device_spec]>"));
+ CHECK_SIMPLE_VARIABLE("export-format", set_export_format, tr("\"binary\" or \"ascii\""));
}
fail_msg_writer() << tr("set: unrecognized argument(s)");
return true;
@@ -7312,7 +7345,7 @@ bool simple_wallet::get_tx_proof(const std::vector<std::string> &args)
{
std::string sig_str = m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, args.size() == 3 ? args[2] : "");
const std::string filename = "monero_tx_proof";
- if (epee::file_io_utils::save_string_to_file(filename, sig_str))
+ if (m_wallet->save_to_file(filename, sig_str, true))
success_msg_writer() << tr("signature file saved to: ") << filename;
else
fail_msg_writer() << tr("failed to save signature file");
@@ -7440,7 +7473,7 @@ bool simple_wallet::check_tx_proof(const std::vector<std::string> &args)
// read signature file
std::string sig_str;
- if (!epee::file_io_utils::load_file_to_string(args[2], sig_str))
+ if (!m_wallet->load_from_file(args[2], sig_str))
{
fail_msg_writer() << tr("failed to load signature file");
return true;
@@ -7524,7 +7557,7 @@ bool simple_wallet::get_spend_proof(const std::vector<std::string> &args)
{
const std::string sig_str = m_wallet->get_spend_proof(txid, args.size() == 2 ? args[1] : "");
const std::string filename = "monero_spend_proof";
- if (epee::file_io_utils::save_string_to_file(filename, sig_str))
+ if (m_wallet->save_to_file(filename, sig_str, true))
success_msg_writer() << tr("signature file saved to: ") << filename;
else
fail_msg_writer() << tr("failed to save signature file");
@@ -7554,7 +7587,7 @@ bool simple_wallet::check_spend_proof(const std::vector<std::string> &args)
return true;
std::string sig_str;
- if (!epee::file_io_utils::load_file_to_string(args[1], sig_str))
+ if (!m_wallet->load_from_file(args[1], sig_str))
{
fail_msg_writer() << tr("failed to load signature file");
return true;
@@ -7613,7 +7646,7 @@ bool simple_wallet::get_reserve_proof(const std::vector<std::string> &args)
{
const std::string sig_str = m_wallet->get_reserve_proof(account_minreserve, args.size() == 2 ? args[1] : "");
const std::string filename = "monero_reserve_proof";
- if (epee::file_io_utils::save_string_to_file(filename, sig_str))
+ if (m_wallet->save_to_file(filename, sig_str, true))
success_msg_writer() << tr("signature file saved to: ") << filename;
else
fail_msg_writer() << tr("failed to save signature file");
@@ -7648,7 +7681,7 @@ bool simple_wallet::check_reserve_proof(const std::vector<std::string> &args)
}
std::string sig_str;
- if (!epee::file_io_utils::load_file_to_string(args[1], sig_str))
+ if (!m_wallet->load_from_file(args[1], sig_str))
{
fail_msg_writer() << tr("failed to load signature file");
return true;
@@ -9011,7 +9044,7 @@ bool simple_wallet::sign(const std::vector<std::string> &args)
std::string filename = args[0];
std::string data;
- bool r = epee::file_io_utils::load_file_to_string(filename, data);
+ bool r = m_wallet->load_from_file(filename, data);
if (!r)
{
fail_msg_writer() << tr("failed to read file ") << filename;
@@ -9037,7 +9070,7 @@ bool simple_wallet::verify(const std::vector<std::string> &args)
std::string signature= args[2];
std::string data;
- bool r = epee::file_io_utils::load_file_to_string(filename, data);
+ bool r = m_wallet->load_from_file(filename, data);
if (!r)
{
fail_msg_writer() << tr("failed to read file ") << filename;
@@ -9255,7 +9288,7 @@ bool simple_wallet::export_outputs(const std::vector<std::string> &args_)
try
{
std::string data = m_wallet->export_outputs_to_str(all);
- bool r = epee::file_io_utils::save_string_to_file(filename, data);
+ bool r = m_wallet->save_to_file(filename, data);
if (!r)
{
fail_msg_writer() << tr("failed to save file ") << filename;
@@ -9288,7 +9321,7 @@ bool simple_wallet::import_outputs(const std::vector<std::string> &args)
std::string filename = args[0];
std::string data;
- bool r = epee::file_io_utils::load_file_to_string(filename, data);
+ bool r = m_wallet->load_from_file(filename, data);
if (!r)
{
fail_msg_writer() << tr("failed to read file ") << filename;
@@ -9489,7 +9522,7 @@ void simple_wallet::commit_or_save(std::vector<tools::wallet2::pending_tx>& ptx_
tx_to_blob(ptx.tx, blob);
const std::string blob_hex = epee::string_tools::buff_to_hex_nodelimer(blob);
const std::string filename = "raw_monero_tx" + (ptx_vector.size() == 1 ? "" : ("_" + std::to_string(i++)));
- if (epee::file_io_utils::save_string_to_file(filename, blob_hex))
+ if (m_wallet->save_to_file(filename, blob_hex, true))
success_msg_writer(true) << tr("Transaction successfully saved to ") << filename << tr(", txid ") << txid;
else
fail_msg_writer() << tr("Failed to save transaction to ") << filename << tr(", txid ") << txid;
@@ -10274,7 +10307,7 @@ void simple_wallet::mms_export(const std::vector<std::string> &args)
if (valid_id)
{
const std::string filename = "mms_message_content";
- if (epee::file_io_utils::save_string_to_file(filename, m.content))
+ if (m_wallet->save_to_file(filename, m.content))
{
success_msg_writer() << tr("Message content saved to: ") << filename;
}
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index 2de390666..cbc1cb6fa 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -146,6 +146,7 @@ namespace cryptonote
bool set_track_uses(const std::vector<std::string> &args = std::vector<std::string>());
bool set_setup_background_mining(const std::vector<std::string> &args = std::vector<std::string>());
bool set_device_name(const std::vector<std::string> &args = std::vector<std::string>());
+ bool set_export_format(const std::vector<std::string> &args = std::vector<std::string>());
bool help(const std::vector<std::string> &args = std::vector<std::string>());
bool start_mining(const std::vector<std::string> &args);
bool stop_mining(const std::vector<std::string> &args);
diff --git a/src/version.cpp.in b/src/version.cpp.in
index 28ce38df7..9121cdf85 100644
--- a/src/version.cpp.in
+++ b/src/version.cpp.in
@@ -2,6 +2,7 @@
#define DEF_MONERO_VERSION "0.14.1.2"
#define DEF_MONERO_RELEASE_NAME "Boron Butterfly"
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
+#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@
#include "version.h"
@@ -9,3 +10,4 @@ const char* const MONERO_VERSION_TAG = DEF_MONERO_VERSION_TAG;
const char* const MONERO_VERSION = DEF_MONERO_VERSION;
const char* const MONERO_RELEASE_NAME = DEF_MONERO_RELEASE_NAME;
const char* const MONERO_VERSION_FULL = DEF_MONERO_VERSION_FULL;
+const bool MONERO_VERSION_IS_RELEASE = DEF_MONERO_VERSION_IS_RELEASE;
diff --git a/src/version.h b/src/version.h
index d1d06c790..b740d3360 100644
--- a/src/version.h
+++ b/src/version.h
@@ -4,3 +4,4 @@ extern const char* const MONERO_VERSION_TAG;
extern const char* const MONERO_VERSION;
extern const char* const MONERO_RELEASE_NAME;
extern const char* const MONERO_VERSION_FULL;
+extern const bool MONERO_VERSION_IS_RELEASE;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 9782e4b1e..155f44129 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -40,6 +40,7 @@
#include <boost/asio/ip/address.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/preprocessor/stringize.hpp>
+#include <openssl/evp.h>
#include "include_base_utils.h"
using namespace epee;
@@ -138,6 +139,8 @@ using namespace cryptonote;
static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";
static const std::string MULTISIG_EXTRA_INFO_MAGIC = "MultisigxV1";
+static const std::string ASCII_OUTPUT_MAGIC = "MoneroAsciiDataV1";
+
namespace
{
std::string get_default_ringdb_path()
@@ -275,6 +278,7 @@ struct options {
const command_line::arg_descriptor<std::string> tx_notify = { "tx-notify" , "Run a program for each new incoming transaction, '%s' will be replaced by the transaction hash" , "" };
const command_line::arg_descriptor<bool> no_dns = {"no-dns", tools::wallet2::tr("Do not use DNS"), false};
const command_line::arg_descriptor<bool> offline = {"offline", tools::wallet2::tr("Do not connect to a daemon, nor use DNS"), false};
+ const command_line::arg_descriptor<std::string> extra_entropy = {"extra-entropy", tools::wallet2::tr("File containing extra entropy to initialize the PRNG (any data, aim for 256 bits of entropy to be useful, wihch typically means more than 256 bits of data)")};
};
void do_prepare_file_names(const std::string& file_path, std::string& keys_file, std::string& wallet_file, std::string &mms_file)
@@ -476,6 +480,15 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
if (command_line::get_arg(vm, opts.offline))
wallet->set_offline();
+ const std::string extra_entropy = command_line::get_arg(vm, opts.extra_entropy);
+ if (!extra_entropy.empty())
+ {
+ std::string data;
+ THROW_WALLET_EXCEPTION_IF(!epee::file_io_utils::load_file_to_string(extra_entropy, data),
+ tools::error::wallet_internal_error, "Failed to load extra entropy from " + extra_entropy);
+ add_extra_entropy_thread_safe(data.data(), data.size());
+ }
+
try
{
if (!command_line::is_arg_defaulted(vm, opts.tx_notify))
@@ -1143,7 +1156,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
m_device_last_key_image_sync(0),
m_use_dns(true),
m_offline(false),
- m_rpc_version(0)
+ m_rpc_version(0),
+ m_export_format(ExportFormat::Binary)
{
}
@@ -1200,6 +1214,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.tx_notify);
command_line::add_arg(desc_params, opts.no_dns);
command_line::add_arg(desc_params, opts.offline);
+ command_line::add_arg(desc_params, opts.extra_entropy);
}
std::pair<std::unique_ptr<wallet2>, tools::password_container> wallet2::make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
@@ -3647,6 +3662,9 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
value2.SetInt(m_original_keys_available ? 1 : 0);
json.AddMember("original_keys_available", value2, json.GetAllocator());
+ value2.SetInt(m_export_format);
+ json.AddMember("export_format", value2, json.GetAllocator());
+
value2.SetUint(1);
json.AddMember("encrypted_secret_keys", value2, json.GetAllocator());
@@ -3684,7 +3702,7 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
std::string tmp_file_name = keys_file_name + ".new";
std::string buf;
r = ::serialization::dump_binary(keys_file_data, buf);
- r = r && epee::file_io_utils::save_string_to_file(tmp_file_name, buf);
+ r = r && save_to_file(tmp_file_name, buf);
CHECK_AND_ASSERT_MES(r, false, "failed to generate wallet keys file " << tmp_file_name);
unlock_keys_file();
@@ -3741,7 +3759,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
wallet2::keys_file_data keys_file_data;
std::string buf;
bool encrypted_secret_keys = false;
- bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf);
+ bool r = load_from_file(keys_file_name, buf);
THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, keys_file_name);
// Decrypt the contents
@@ -3754,7 +3772,6 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
crypto::chacha20(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject())
crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
-
// The contents should be JSON if the wallet follows the new format.
if (json.Parse(account_data.c_str()).HasParseError())
{
@@ -3793,6 +3810,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_subaddress_lookahead_major = SUBADDRESS_LOOKAHEAD_MAJOR;
m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR;
m_original_keys_available = false;
+ m_export_format = ExportFormat::Binary;
m_device_name = "";
m_device_derivation_path = "";
m_key_device_type = hw::device::device_type::SOFTWARE;
@@ -3954,6 +3972,9 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, encrypted_secret_keys, uint32_t, Uint, false, false);
encrypted_secret_keys = field_encrypted_secret_keys;
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, export_format, ExportFormat, Int, false, Binary);
+ m_export_format = field_export_format;
+
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, device_name, std::string, String, false, std::string());
if (m_device_name.empty())
{
@@ -4101,7 +4122,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
wallet2::keys_file_data keys_file_data;
std::string buf;
bool encrypted_secret_keys = false;
- bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf);
+ bool r = load_from_file(keys_file_name, buf);
THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, keys_file_name);
// Decrypt the contents
@@ -4186,7 +4207,7 @@ void wallet2::create_keys_file(const std::string &wallet_, bool watch_only, cons
if (create_address_file)
{
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
+ r = save_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype), true);
if(!r) MERROR("String with address text not saved");
}
}
@@ -4208,7 +4229,7 @@ bool wallet2::query_device(hw::device::device_type& device_type, const std::stri
rapidjson::Document json;
wallet2::keys_file_data keys_file_data;
std::string buf;
- bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf);
+ bool r = load_from_file(keys_file_name, buf);
THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, keys_file_name);
// Decrypt the contents
@@ -4757,7 +4778,7 @@ std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &passwor
if (boost::filesystem::exists(m_wallet_file + ".address.txt"))
{
- r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype));
+ r = save_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype), true);
if(!r) MERROR("String with address text not saved");
}
}
@@ -5266,7 +5287,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
{
wallet2::cache_file_data cache_file_data;
std::string buf;
- bool r = epee::file_io_utils::load_file_to_string(m_wallet_file, buf, std::numeric_limits<size_t>::max());
+ bool r = load_from_file(m_wallet_file, buf, std::numeric_limits<size_t>::max());
THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file);
// try to read it as an encrypted cache
@@ -5501,7 +5522,7 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
{
// save address to the new file
const std::string address_file = m_wallet_file + ".address.txt";
- r = file_io_utils::save_string_to_file(address_file, m_account.get_public_address_str(m_nettype));
+ r = save_to_file(address_file, m_account.get_public_address_str(m_nettype), true);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file);
}
// remove old wallet file
@@ -5536,7 +5557,7 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
binary_archive<true> oar(oss);
bool success = ::serialization::serialize(oar, cache_file_data);
if (success) {
- success = epee::file_io_utils::save_string_to_file(new_file, oss.str());
+ success = save_to_file(new_file, oss.str());
}
THROW_WALLET_EXCEPTION_IF(!success, error::file_save_error, new_file);
#else
@@ -6164,7 +6185,7 @@ bool wallet2::save_tx(const std::vector<pending_tx>& ptx_vector, const std::stri
std::string ciphertext = dump_tx_to_str(ptx_vector);
if (ciphertext.empty())
return false;
- return epee::file_io_utils::save_string_to_file(filename, ciphertext);
+ return save_to_file(filename, ciphertext);
}
//----------------------------------------------------------------------------------------------------
std::string wallet2::dump_tx_to_str(const std::vector<pending_tx> &ptx_vector) const
@@ -6206,7 +6227,7 @@ bool wallet2::load_unsigned_tx(const std::string &unsigned_filename, unsigned_tx
LOG_PRINT_L0("File " << unsigned_filename << " does not exist: " << errcode);
return false;
}
- if (!epee::file_io_utils::load_file_to_string(unsigned_filename.c_str(), s))
+ if (!load_from_file(unsigned_filename.c_str(), s))
{
LOG_PRINT_L0("Failed to load from " << unsigned_filename);
return false;
@@ -6427,7 +6448,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f
return false;
}
- if (!epee::file_io_utils::save_string_to_file(signed_filename, ciphertext))
+ if (!save_to_file(signed_filename, ciphertext))
{
LOG_PRINT_L0("Failed to save file to " << signed_filename);
return false;
@@ -6439,7 +6460,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f
{
std::string tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(signed_txes.ptx[i].tx));
std::string raw_filename = signed_filename + "_raw" + (signed_txes.ptx.size() == 1 ? "" : ("_" + std::to_string(i)));
- if (!epee::file_io_utils::save_string_to_file(raw_filename, tx_as_hex))
+ if (!save_to_file(raw_filename, tx_as_hex))
{
LOG_PRINT_L0("Failed to save file to " << raw_filename);
return false;
@@ -6487,7 +6508,7 @@ bool wallet2::load_tx(const std::string &signed_filename, std::vector<tools::wal
return false;
}
- if (!epee::file_io_utils::load_file_to_string(signed_filename.c_str(), s))
+ if (!load_from_file(signed_filename.c_str(), s))
{
LOG_PRINT_L0("Failed to load from " << signed_filename);
return false;
@@ -6618,7 +6639,7 @@ bool wallet2::save_multisig_tx(const multisig_tx_set &txs, const std::string &fi
std::string ciphertext = save_multisig_tx(txs);
if (ciphertext.empty())
return false;
- return epee::file_io_utils::save_string_to_file(filename, ciphertext);
+ return save_to_file(filename, ciphertext);
}
//----------------------------------------------------------------------------------------------------
wallet2::multisig_tx_set wallet2::make_multisig_tx_set(const std::vector<pending_tx>& ptx_vector) const
@@ -6646,7 +6667,7 @@ bool wallet2::save_multisig_tx(const std::vector<pending_tx>& ptx_vector, const
std::string ciphertext = save_multisig_tx(ptx_vector);
if (ciphertext.empty())
return false;
- return epee::file_io_utils::save_string_to_file(filename, ciphertext);
+ return save_to_file(filename, ciphertext);
}
//----------------------------------------------------------------------------------------------------
bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx_set &exported_txs) const
@@ -6737,7 +6758,7 @@ bool wallet2::load_multisig_tx_from_file(const std::string &filename, multisig_t
LOG_PRINT_L0("File " << filename << " does not exist: " << errcode);
return false;
}
- if (!epee::file_io_utils::load_file_to_string(filename.c_str(), s))
+ if (!load_from_file(filename.c_str(), s))
{
LOG_PRINT_L0("Failed to load from " << filename);
return false;
@@ -11633,7 +11654,7 @@ bool wallet2::export_key_images(const std::string &filename, bool all) const
// encrypt data, keep magic plaintext
PERF_TIMER(export_key_images_encrypt);
std::string ciphertext = encrypt_with_view_secret_key(data);
- return epee::file_io_utils::save_string_to_file(filename, magic + ciphertext);
+ return save_to_file(filename, magic + ciphertext);
}
//----------------------------------------------------------------------------------------------------
@@ -11698,7 +11719,7 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent
{
PERF_TIMER(import_key_images_fsu);
std::string data;
- bool r = epee::file_io_utils::load_file_to_string(filename, data);
+ bool r = load_from_file(filename, data);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, std::string(tr("failed to read file ")) + filename);
@@ -13102,6 +13123,83 @@ void wallet2::throw_on_rpc_response_error(const boost::optional<std::string> &st
THROW_WALLET_EXCEPTION_IF(*status != CORE_RPC_STATUS_OK, tools::error::wallet_generic_rpc_error, method, m_trusted_daemon ? *status : "daemon error");
}
//----------------------------------------------------------------------------------------------------
+
+bool wallet2::save_to_file(const std::string& path_to_file, const std::string& raw, bool is_printable) const
+{
+ if (is_printable || m_export_format == ExportFormat::Binary)
+ {
+ return epee::file_io_utils::save_string_to_file(path_to_file, raw);
+ }
+
+ FILE *fp = fopen(path_to_file.c_str(), "w+");
+ // Save the result b/c we need to close the fp before returning success/failure.
+ int write_result = PEM_write(fp, ASCII_OUTPUT_MAGIC.c_str(), "", (const unsigned char *) raw.c_str(), raw.length());
+ fclose(fp);
+
+ if (write_result == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+//----------------------------------------------------------------------------------------------------
+
+bool wallet2::load_from_file(const std::string& path_to_file, std::string& target_str,
+ size_t max_size)
+{
+ std::string data;
+ bool r = epee::file_io_utils::load_file_to_string(path_to_file, data, max_size);
+ if (!r)
+ {
+ return false;
+ }
+
+ if (!boost::algorithm::contains(boost::make_iterator_range(data.begin(), data.end()), ASCII_OUTPUT_MAGIC))
+ {
+ // It's NOT our ascii dump.
+ target_str = std::move(data);
+ return true;
+ }
+
+ // Creating a BIO and calling PEM_read_bio instead of simpler PEM_read
+ // to avoid reading the file from disk twice.
+ BIO* b = BIO_new_mem_buf((const void*) data.data(), data.length());
+
+ char *name = NULL;
+ char *header = NULL;
+ unsigned char *openssl_data = NULL;
+ long len = 0;
+
+ // Save the result b/c we need to free the data before returning success/failure.
+ int success = PEM_read_bio(b, &name, &header, &openssl_data, &len);
+
+ try
+ {
+ target_str = std::string((const char*) openssl_data, len);
+ }
+ catch (...)
+ {
+ success = 0;
+ }
+
+ OPENSSL_free((void *) name);
+ OPENSSL_free((void *) header);
+ OPENSSL_free((void *) openssl_data);
+ BIO_free(b);
+
+ if (success == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+//----------------------------------------------------------------------------------------------------
void wallet2::hash_m_transfer(const transfer_details & transfer, crypto::hash &hash) const
{
KECCAK_CTX state;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index c2e34dd76..e1aca1e89 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -227,6 +227,11 @@ private:
BackgroundMiningNo = 2,
};
+ enum ExportFormat {
+ Binary = 0,
+ Ascii,
+ };
+
static const char* tr(const char* str);
static bool has_testnet_option(const boost::program_options::variables_map& vm);
@@ -1050,6 +1055,8 @@ private:
void device_name(const std::string & device_name) { m_device_name = device_name; }
const std::string & device_derivation_path() const { return m_device_derivation_path; }
void device_derivation_path(const std::string &device_derivation_path) { m_device_derivation_path = device_derivation_path; }
+ const ExportFormat & export_format() const { return m_export_format; }
+ inline void set_export_format(const ExportFormat& export_format) { m_export_format = export_format; }
bool get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const;
void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys);
@@ -1300,6 +1307,9 @@ private:
bool frozen(const crypto::key_image &ki) const;
bool frozen(const transfer_details &td) const;
+ bool save_to_file(const std::string& path_to_file, const std::string& binary, bool is_printable = false) const;
+ static bool load_from_file(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000);
+
uint64_t get_bytes_sent() const;
uint64_t get_bytes_received() const;
@@ -1546,6 +1556,8 @@ private:
std::shared_ptr<tools::Notify> m_tx_notify;
std::unique_ptr<wallet_device_callback> m_device_callback;
+
+ ExportFormat m_export_format;
};
}
BOOST_CLASS_VERSION(tools::wallet2, 28)
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index c64b662f3..7c87e7114 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -36,6 +36,7 @@
#include "include_base_utils.h"
using namespace epee;
+#include "version.h"
#include "wallet_rpc_server.h"
#include "wallet/wallet_args.h"
#include "common/command_line.h"
@@ -4188,6 +4189,7 @@ namespace tools
bool wallet_rpc_server::on_get_version(const wallet_rpc::COMMAND_RPC_GET_VERSION::request& req, wallet_rpc::COMMAND_RPC_GET_VERSION::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
res.version = WALLET_RPC_VERSION;
+ res.release = MONERO_VERSION_IS_RELEASE;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 4504ac752..2dfe6db85 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -47,7 +47,7 @@
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define WALLET_RPC_VERSION_MAJOR 1
-#define WALLET_RPC_VERSION_MINOR 13
+#define WALLET_RPC_VERSION_MINOR 14
#define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
namespace tools
@@ -2418,9 +2418,11 @@ namespace wallet_rpc
struct response_t
{
uint32_t version;
+ bool release;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(version)
+ KV_SERIALIZE(release)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp
index c32e0df20..bd7414c59 100644
--- a/tests/performance_tests/main.cpp
+++ b/tests/performance_tests/main.cpp
@@ -57,7 +57,6 @@
#include "rct_mlsag.h"
#include "equality.h"
#include "range_proof.h"
-#include "rct_mlsag.h"
#include "bulletproof.h"
#include "crypto_ops.h"
#include "multiexp.h"
@@ -214,14 +213,8 @@ int main(int argc, char** argv)
TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 32);
TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 16384);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 3, false);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 5, false);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 10, false);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 100, false);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 3, true);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 5, true);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 10, true);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 100, true);
+ TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, false);
+ TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, true);
TEST_PERFORMANCE2(filter, p, test_equality, memcmp32, true);
TEST_PERFORMANCE2(filter, p, test_equality, memcmp32, false);
@@ -251,15 +244,6 @@ int main(int argc, char** argv)
TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, false, 2, 1, 1, 0, 64);
TEST_PERFORMANCE6(filter, p, test_aggregated_bulletproof, true, 2, 1, 1, 0, 64); // 64 proof, each with 2 amounts
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 3, false);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 5, false);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 10, false);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 100, false);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 3, true);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 5, true);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 10, true);
- TEST_PERFORMANCE3(filter, p, test_ringct_mlsag, 1, 100, true);
-
TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_sc_add);
TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_sc_sub);
TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_sc_mul);
diff --git a/tests/performance_tests/rct_mlsag.h b/tests/performance_tests/rct_mlsag.h
index 0141710f7..59eae074e 100644
--- a/tests/performance_tests/rct_mlsag.h
+++ b/tests/performance_tests/rct_mlsag.h
@@ -35,13 +35,13 @@
#include "single_tx_test_base.h"
-template<size_t inputs, size_t ring_size, bool ver>
+template<size_t ring_size, bool ver>
class test_ringct_mlsag : public single_tx_test_base
{
public:
static const size_t cols = ring_size;
- static const size_t rows = inputs;
- static const size_t loop_count = 100;
+ static const size_t rows = 2; // single spend and commitment data
+ static const size_t loop_count = 1000;
bool init()
{
@@ -65,7 +65,7 @@ public:
{
sk[j] = xm[ind][j];
}
- IIccss = MLSAG_Gen(rct::identity(), P, sk, NULL, NULL, ind, rows, hw::get_device("default"));
+ IIccss = MLSAG_Gen(rct::identity(), P, sk, NULL, NULL, ind, rows-1, hw::get_device("default"));
return true;
}
@@ -73,9 +73,9 @@ public:
bool test()
{
if (ver)
- MLSAG_Ver(rct::identity(), P, IIccss, rows);
+ MLSAG_Ver(rct::identity(), P, IIccss, rows-1);
else
- MLSAG_Gen(rct::identity(), P, sk, NULL, NULL, ind, rows, hw::get_device("default"));
+ MLSAG_Gen(rct::identity(), P, sk, NULL, NULL, ind, rows-1, hw::get_device("default"));
return true;
}
diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp
index d2b2c3109..075aeac40 100644
--- a/tests/unit_tests/ringct.cpp
+++ b/tests/unit_tests/ringct.cpp
@@ -788,7 +788,20 @@ TEST(ringct, HPow2)
{
key G = scalarmultBase(d2h(1));
- key H = hashToPointSimple(G);
+ // Note that H is computed differently than standard hashing
+ // This method is not guaranteed to return a curvepoint for all inputs
+ // Don't use it elsewhere
+ key H = cn_fast_hash(G);
+ ge_p3 H_p3;
+ int decode = ge_frombytes_vartime(&H_p3, H.bytes);
+ ASSERT_EQ(decode, 0); // this is known to pass for the particular value G
+ ge_p2 H_p2;
+ ge_p3_to_p2(&H_p2, &H_p3);
+ ge_p1p1 H8_p1p1;
+ ge_mul8(&H8_p1p1, &H_p2);
+ ge_p1p1_to_p3(&H_p3, &H8_p1p1);
+ ge_p3_tobytes(H.bytes, &H_p3);
+
for (int j = 0 ; j < ATOMS ; j++) {
ASSERT_TRUE(equalKeys(H, H2[j]));
addKeys(H, H, H);
diff --git a/utils/build_scripts/android32.Dockerfile b/utils/build_scripts/android32.Dockerfile
index e49bdc652..4e4f40276 100644
--- a/utils/build_scripts/android32.Dockerfile
+++ b/utils/build_scripts/android32.Dockerfile
@@ -1,6 +1,6 @@
FROM debian:stable
-RUN apt-get update && apt-get install -y unzip automake build-essential curl file pkg-config git python libtool
+RUN apt-get update && apt-get install -y unzip automake build-essential curl file pkg-config git python libtool libtinfo5
WORKDIR /opt/android
## INSTALL ANDROID SDK
diff --git a/utils/build_scripts/android64.Dockerfile b/utils/build_scripts/android64.Dockerfile
index c4464fa84..90eeb4bae 100644
--- a/utils/build_scripts/android64.Dockerfile
+++ b/utils/build_scripts/android64.Dockerfile
@@ -1,6 +1,6 @@
FROM debian:stable
-RUN apt-get update && apt-get install -y unzip automake build-essential curl file pkg-config git python libtool
+RUN apt-get update && apt-get install -y unzip automake build-essential curl file pkg-config git python libtool libtinfo5
WORKDIR /opt/android
## INSTALL ANDROID SDK