mirror of
https://git.wownero.com/wownero/wownero.git
synced 2024-08-15 01:03:23 +00:00
Merge pull request #6288
0349347e
ringdb: use a different iv for key and data in rings table (moneromooo-monero)7b882087
simplewallet: reword mixin in user message in terms of ring size (moneromooo-monero)f507a43a
wallet2: do not remove known rings when a tx fails (moneromooo-monero)
This commit is contained in:
commit
5ba6eef272
3 changed files with 38 additions and 20 deletions
|
@ -1691,7 +1691,7 @@ bool simple_wallet::print_ring(const std::vector<std::string> &args)
|
||||||
rings.push_back({key_image, ring});
|
rings.push_back({key_image, ring});
|
||||||
else if (!m_wallet->get_rings(txid, rings))
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||||
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.ringdb"
|
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.ringdb"
|
||||||
|
|
||||||
|
#define V1TAG ((uint64_t)798237759845202)
|
||||||
|
|
||||||
static const char zerokey[8] = {0};
|
static const char zerokey[8] = {0};
|
||||||
static const MDB_val zerokeyval = { sizeof(zerokey), (void *)zerokey };
|
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;
|
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;
|
std::string s;
|
||||||
|
s += tools::get_varint_data(tag);
|
||||||
for (uint64_t out: ring)
|
for (uint64_t out: ring)
|
||||||
s += tools::get_varint_data(out);
|
s += tools::get_varint_data(out);
|
||||||
return s;
|
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;
|
std::vector<uint64_t> ring;
|
||||||
int read = 0;
|
int read = 0;
|
||||||
|
@ -81,6 +84,13 @@ static std::vector<uint64_t> decompress_ring(const std::string &s)
|
||||||
std::string tmp(i, s.cend());
|
std::string tmp(i, s.cend());
|
||||||
read = tools::read_varint(tmp.begin(), tmp.end(), out);
|
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");
|
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);
|
ring.push_back(out);
|
||||||
}
|
}
|
||||||
return ring;
|
return ring;
|
||||||
|
@ -93,25 +103,27 @@ std::string get_rings_filename(boost::filesystem::path filename)
|
||||||
return filename.string();
|
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";
|
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, &key_image, sizeof(key_image));
|
||||||
memcpy(buffer + sizeof(key_image), &key, sizeof(key));
|
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), salt, sizeof(salt));
|
||||||
|
memcpy(buffer + sizeof(key_image) + sizeof(key) + sizeof(salt), &field, sizeof(field));
|
||||||
crypto::hash hash;
|
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");
|
static_assert(sizeof(hash) >= CHACHA_IV_SIZE, "Incompatible hash and chacha IV sizes");
|
||||||
crypto::chacha_iv iv;
|
crypto::chacha_iv iv;
|
||||||
memcpy(&iv, &hash, CHACHA_IV_SIZE);
|
memcpy(&iv, &hash, CHACHA_IV_SIZE);
|
||||||
return iv;
|
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;
|
std::string ciphertext;
|
||||||
ciphertext.resize(plaintext.size() + sizeof(iv));
|
ciphertext.resize(plaintext.size() + sizeof(iv));
|
||||||
crypto::chacha20(plaintext.data(), plaintext.size(), key, iv, &ciphertext[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;
|
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;
|
std::string plaintext;
|
||||||
THROW_WALLET_EXCEPTION_IF(ciphertext.size() < sizeof(iv), tools::error::wallet_internal_error, "Bad ciphertext text");
|
THROW_WALLET_EXCEPTION_IF(ciphertext.size() < sizeof(iv), tools::error::wallet_internal_error, "Bad ciphertext text");
|
||||||
plaintext.resize(ciphertext.size() - sizeof(iv));
|
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)
|
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;
|
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_data = (void*)key_ciphertext.data();
|
||||||
key.mv_size = key_ciphertext.size();
|
key.mv_size = key_ciphertext.size();
|
||||||
std::string compressed_ring = compress_ring(relative_ring);
|
std::string compressed_ring = compress_ring(relative_ring, V1TAG);
|
||||||
std::string data_ciphertext = encrypt(compressed_ring, key_image, chacha_key);
|
std::string data_ciphertext = encrypt(compressed_ring, key_image, chacha_key, 1);
|
||||||
data.mv_size = data_ciphertext.size();
|
data.mv_size = data_ciphertext.size();
|
||||||
data.mv_data = (void*)data_ciphertext.c_str();
|
data.mv_data = (void*)data_ciphertext.c_str();
|
||||||
int dbr = mdb_put(txn, dbi, &key, &data, 0);
|
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)
|
for (const crypto::key_image &key_image: key_images)
|
||||||
{
|
{
|
||||||
MDB_val key, data;
|
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_data = (void*)key_ciphertext.data();
|
||||||
key.mv_size = key_ciphertext.size();
|
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;
|
tx_active = true;
|
||||||
|
|
||||||
MDB_val key, data;
|
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_data = (void*)key_ciphertext.data();
|
||||||
key.mv_size = key_ciphertext.size();
|
key.mv_size = key_ciphertext.size();
|
||||||
dbr = mdb_get(txn, dbi_rings, &key, &data);
|
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;
|
return false;
|
||||||
THROW_WALLET_EXCEPTION_IF(data.mv_size <= 0, tools::error::wallet_internal_error, "Invalid ring data size");
|
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);
|
bool try_v0 = false;
|
||||||
outs = decompress_ring(data_plaintext);
|
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("Found ring for key image " << key_image << ":");
|
||||||
MDEBUG("Relative: " << boost::join(outs | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
|
MDEBUG("Relative: " << boost::join(outs | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
|
||||||
outs = cryptonote::relative_output_offsets_to_absolute(outs);
|
outs = cryptonote::relative_output_offsets_to_absolute(outs);
|
||||||
|
|
|
@ -2934,7 +2934,6 @@ void wallet2::update_pool_state(std::vector<std::tuple<cryptonote::transaction,
|
||||||
pit->second.m_state = wallet2::unconfirmed_transfer_details::failed;
|
pit->second.m_state = wallet2::unconfirmed_transfer_details::failed;
|
||||||
|
|
||||||
// the inputs aren't spent anymore, since the tx 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)
|
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))
|
if (pit->second.m_tx.vin[vini].type() == typeid(txin_to_key))
|
||||||
|
|
Loading…
Reference in a new issue