aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/simplewallet/simplewallet.cpp2
-rw-r--r--src/wallet/ringdb.cpp55
-rw-r--r--src/wallet/wallet2.cpp1
3 files changed, 38 insertions, 20 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 19e3656c2..d981a48b8 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -1691,7 +1691,7 @@ bool simple_wallet::print_ring(const std::vector<std::string> &args)
rings.push_back({key_image, ring});
else if (!m_wallet->get_rings(txid, rings))
{
- fail_msg_writer() << tr("Key image either not spent, or spent with mixin 0");
+ fail_msg_writer() << tr("Key image either not spent, or spent with ring size 1");
return true;
}
diff --git a/src/wallet/ringdb.cpp b/src/wallet/ringdb.cpp
index b7efdd75c..5e88ea788 100644
--- a/src/wallet/ringdb.cpp
+++ b/src/wallet/ringdb.cpp
@@ -39,6 +39,8 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.ringdb"
+#define V1TAG ((uint64_t)798237759845202)
+
static const char zerokey[8] = {0};
static const MDB_val zerokeyval = { sizeof(zerokey), (void *)zerokey };
@@ -63,15 +65,16 @@ static int compare_uint64(const MDB_val *a, const MDB_val *b)
return va < vb ? -1 : va > vb;
}
-static std::string compress_ring(const std::vector<uint64_t> &ring)
+static std::string compress_ring(const std::vector<uint64_t> &ring, uint64_t tag)
{
std::string s;
+ s += tools::get_varint_data(tag);
for (uint64_t out: ring)
s += tools::get_varint_data(out);
return s;
}
-static std::vector<uint64_t> decompress_ring(const std::string &s)
+static std::vector<uint64_t> decompress_ring(const std::string &s, uint64_t tag)
{
std::vector<uint64_t> ring;
int read = 0;
@@ -81,6 +84,13 @@ static std::vector<uint64_t> decompress_ring(const std::string &s)
std::string tmp(i, s.cend());
read = tools::read_varint(tmp.begin(), tmp.end(), out);
THROW_WALLET_EXCEPTION_IF(read <= 0 || read > 256, tools::error::wallet_internal_error, "Internal error decompressing ring");
+ if (tag)
+ {
+ if (tag != out)
+ return {};
+ tag = 0;
+ continue;
+ }
ring.push_back(out);
}
return ring;
@@ -93,25 +103,27 @@ std::string get_rings_filename(boost::filesystem::path filename)
return filename.string();
}
-static crypto::chacha_iv make_iv(const crypto::key_image &key_image, const crypto::chacha_key &key)
+static crypto::chacha_iv make_iv(const crypto::key_image &key_image, const crypto::chacha_key &key, uint8_t field)
{
static const char salt[] = "ringdsb";
- uint8_t buffer[sizeof(key_image) + sizeof(key) + sizeof(salt)];
+ uint8_t buffer[sizeof(key_image) + sizeof(key) + sizeof(salt) + sizeof(field)];
memcpy(buffer, &key_image, sizeof(key_image));
memcpy(buffer + sizeof(key_image), &key, sizeof(key));
memcpy(buffer + sizeof(key_image) + sizeof(key), salt, sizeof(salt));
+ memcpy(buffer + sizeof(key_image) + sizeof(key) + sizeof(salt), &field, sizeof(field));
crypto::hash hash;
- crypto::cn_fast_hash(buffer, sizeof(buffer), hash.data);
+ // if field is 0, backward compat mode: hash without the field
+ crypto::cn_fast_hash(buffer, sizeof(buffer) - !field, hash.data);
static_assert(sizeof(hash) >= CHACHA_IV_SIZE, "Incompatible hash and chacha IV sizes");
crypto::chacha_iv iv;
memcpy(&iv, &hash, CHACHA_IV_SIZE);
return iv;
}
-static std::string encrypt(const std::string &plaintext, const crypto::key_image &key_image, const crypto::chacha_key &key)
+static std::string encrypt(const std::string &plaintext, const crypto::key_image &key_image, const crypto::chacha_key &key, uint8_t field)
{
- const crypto::chacha_iv iv = make_iv(key_image, key);
+ const crypto::chacha_iv iv = make_iv(key_image, key, field);
std::string ciphertext;
ciphertext.resize(plaintext.size() + sizeof(iv));
crypto::chacha20(plaintext.data(), plaintext.size(), key, iv, &ciphertext[sizeof(iv)]);
@@ -119,14 +131,14 @@ static std::string encrypt(const std::string &plaintext, const crypto::key_image
return ciphertext;
}
-static std::string encrypt(const crypto::key_image &key_image, const crypto::chacha_key &key)
+static std::string encrypt(const crypto::key_image &key_image, const crypto::chacha_key &key, uint8_t field)
{
- return encrypt(std::string((const char*)&key_image, sizeof(key_image)), key_image, key);
+ return encrypt(std::string((const char*)&key_image, sizeof(key_image)), key_image, key, field);
}
-static std::string decrypt(const std::string &ciphertext, const crypto::key_image &key_image, const crypto::chacha_key &key)
+static std::string decrypt(const std::string &ciphertext, const crypto::key_image &key_image, const crypto::chacha_key &key, uint8_t field)
{
- const crypto::chacha_iv iv = make_iv(key_image, key);
+ const crypto::chacha_iv iv = make_iv(key_image, key, field);
std::string plaintext;
THROW_WALLET_EXCEPTION_IF(ciphertext.size() < sizeof(iv), tools::error::wallet_internal_error, "Bad ciphertext text");
plaintext.resize(ciphertext.size() - sizeof(iv));
@@ -137,11 +149,11 @@ static std::string decrypt(const std::string &ciphertext, const crypto::key_imag
static void store_relative_ring(MDB_txn *txn, MDB_dbi &dbi, const crypto::key_image &key_image, const std::vector<uint64_t> &relative_ring, const crypto::chacha_key &chacha_key)
{
MDB_val key, data;
- std::string key_ciphertext = encrypt(key_image, chacha_key);
+ std::string key_ciphertext = encrypt(key_image, chacha_key, 0);
key.mv_data = (void*)key_ciphertext.data();
key.mv_size = key_ciphertext.size();
- std::string compressed_ring = compress_ring(relative_ring);
- std::string data_ciphertext = encrypt(compressed_ring, key_image, chacha_key);
+ std::string compressed_ring = compress_ring(relative_ring, V1TAG);
+ std::string data_ciphertext = encrypt(compressed_ring, key_image, chacha_key, 1);
data.mv_size = data_ciphertext.size();
data.mv_data = (void*)data_ciphertext.c_str();
int dbr = mdb_put(txn, dbi, &key, &data, 0);
@@ -297,7 +309,7 @@ bool ringdb::remove_rings(const crypto::chacha_key &chacha_key, const std::vecto
for (const crypto::key_image &key_image: key_images)
{
MDB_val key, data;
- std::string key_ciphertext = encrypt(key_image, chacha_key);
+ std::string key_ciphertext = encrypt(key_image, chacha_key, 0);
key.mv_data = (void*)key_ciphertext.data();
key.mv_size = key_ciphertext.size();
@@ -349,7 +361,7 @@ bool ringdb::get_ring(const crypto::chacha_key &chacha_key, const crypto::key_im
tx_active = true;
MDB_val key, data;
- std::string key_ciphertext = encrypt(key_image, chacha_key);
+ std::string key_ciphertext = encrypt(key_image, chacha_key, 0);
key.mv_data = (void*)key_ciphertext.data();
key.mv_size = key_ciphertext.size();
dbr = mdb_get(txn, dbi_rings, &key, &data);
@@ -358,8 +370,15 @@ bool ringdb::get_ring(const crypto::chacha_key &chacha_key, const crypto::key_im
return false;
THROW_WALLET_EXCEPTION_IF(data.mv_size <= 0, tools::error::wallet_internal_error, "Invalid ring data size");
- std::string data_plaintext = decrypt(std::string((const char*)data.mv_data, data.mv_size), key_image, chacha_key);
- outs = decompress_ring(data_plaintext);
+ bool try_v0 = false;
+ std::string data_plaintext = decrypt(std::string((const char*)data.mv_data, data.mv_size), key_image, chacha_key, 1);
+ try { outs = decompress_ring(data_plaintext, V1TAG); if (outs.empty()) try_v0 = true; }
+ catch(...) { try_v0 = true; }
+ if (try_v0)
+ {
+ data_plaintext = decrypt(std::string((const char*)data.mv_data, data.mv_size), key_image, chacha_key, 0);
+ outs = decompress_ring(data_plaintext, 0);
+ }
MDEBUG("Found ring for key image " << key_image << ":");
MDEBUG("Relative: " << boost::join(outs | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
outs = cryptonote::relative_output_offsets_to_absolute(outs);
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 7ee32a436..97711c7cd 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -2934,7 +2934,6 @@ void wallet2::update_pool_state(std::vector<std::tuple<cryptonote::transaction,
pit->second.m_state = wallet2::unconfirmed_transfer_details::failed;
// the inputs aren't spent anymore, since the tx failed
- remove_rings(pit->second.m_tx);
for (size_t vini = 0; vini < pit->second.m_tx.vin.size(); ++vini)
{
if (pit->second.m_tx.vin[vini].type() == typeid(txin_to_key))