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
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user