diff --git a/src/cryptonote_core/beldex_name_system.cpp b/src/cryptonote_core/beldex_name_system.cpp index be2aae0bc57..751b62ae6c2 100755 --- a/src/cryptonote_core/beldex_name_system.cpp +++ b/src/cryptonote_core/beldex_name_system.cpp @@ -976,14 +976,14 @@ bool mapping_value::validate(cryptonote::network_type nettype, mapping_type type } else if(type == mapping_type::eth_addr) { + if (check_condition(value.size() < 2 || !tools::starts_with(value, "0x"), reason, "BNS type=eth_addr, specifies mapping from name -> eth addr where the addr is not prefixed with 0x, given eth addr=", value)) + return false; + std::string_view value_eth = value.substr(2); if(check_condition(value_eth.size() != 2*ETH_ADDR_BINARY_LENGTH, reason, "The value=", value, " is not the required ", 2*ETH_ADDR_BINARY_LENGTH, "-character hex string eth address, length=", value.size())) return false; - - if (check_condition(!oxenc::is_hex(value_eth), reason, ", specifies name -> value mapping where the value is not a hex string given value=")) - return false; - if (check_condition(!tools::starts_with(value, "0x"), reason, "BNS type=eth_addr, specifies mapping from name -> ed25519 key where the key is not prefixed with 0x, given ed25519=", value)) + if (check_condition(!oxenc::is_hex(value_eth), reason, ", specifies name -> value mapping where the value is not a hex string given value=")) return false; if (blob) // NOTE: Given blob, write the binary output @@ -1012,7 +1012,6 @@ bool mapping_value::validate(cryptonote::network_type nettype, mapping_type type blob->len = value.size() / 2; assert(blob->len <= blob->buffer.size()); oxenc::from_hex(value.begin(), value.end(), blob->buffer.begin()); - } } diff --git a/src/cryptonote_core/master_node_list.cpp b/src/cryptonote_core/master_node_list.cpp index 404e12fcffa..c6ad314159a 100755 --- a/src/cryptonote_core/master_node_list.cpp +++ b/src/cryptonote_core/master_node_list.cpp @@ -2772,7 +2772,7 @@ namespace master_nodes cryptonote::db_wtxn_guard txn_guard{db}; db.set_master_node_data(blob, long_term); } - MGINFO(fmt::format("Stored {} master node data: {} in {:.2f}s", what, + MCINFO("omq", fmt::format("Stored {} master node data: {} in {:.2f}s", what, tools::get_human_readable_bytes(bytes), std::chrono::duration{std::chrono::steady_clock::now() - started}.count())); return true; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 2c3641add6d..0985cd2f70d 100755 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -7593,6 +7593,8 @@ bool wallet2::parse_unsigned_tx_from_str(std::string_view s, unsigned_tx_set &ex LOG_PRINT_L0("Bad magic from unsigned tx"); return false; } + if (s.size() <= UNSIGNED_TX_PREFIX_NOVER.size()) + throw std::out_of_range("Empty unsigned tx"); s.remove_prefix(UNSIGNED_TX_PREFIX_NOVER.size()); const char version = s[0]; s = s.substr(1); @@ -7877,6 +7879,8 @@ bool wallet2::parse_tx_from_str(std::string_view s, std::vector seen_key_images; total = spent = 0; for (size_t i = 0; i < proofs.size(); ++i) { const reserve_proof_entry& proof = proofs[i]; - THROW_WALLET_EXCEPTION_IF(gettx_res["txs"][i]["in_pool"].get(), error::wallet_internal_error, "Tx is unconfirmed"); + THROW_WALLET_EXCEPTION_IF(!seen_key_images.insert(proof.key_image).second, error::wallet_internal_error, "Duplicate key image in reserve proof"); + THROW_WALLET_EXCEPTION_IF(gettx_res["txs"][i].value("in_pool", false), error::wallet_internal_error, "Tx is unconfirmed"); cryptonote::transaction tx; crypto::hash tx_hash; @@ -13881,8 +13887,9 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr THROW_WALLET_EXCEPTION_IF(proof.index_in_tx >= tx.vout.size(), error::wallet_internal_error, "index_in_tx is out of bound"); - const cryptonote::txout_to_key* const out_key = std::get_if(std::addressof(tx.vout[proof.index_in_tx].target)); - THROW_WALLET_EXCEPTION_IF(!out_key, error::wallet_internal_error, "Output key wasn't found"); + crypto::public_key out_key_pub = crypto::null_pkey; + if (const cryptonote::txout_to_key* ok = std::get_if(&tx.vout[proof.index_in_tx].target)) + out_key_pub = ok->key; // TODO(beldex): We should make a catch-all function that gets all the public // keys out into an array and iterate through all insteaad of multiple code @@ -13929,7 +13936,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr return false; // check signature for key image - ok = crypto::check_key_image_signature(proof.key_image, out_key->key, proof.key_image_sig); + ok = crypto::check_key_image_signature(proof.key_image, out_key_pub, proof.key_image_sig); if (!ok) return false; @@ -13937,7 +13944,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr crypto::key_derivation derivation; THROW_WALLET_EXCEPTION_IF(!crypto::generate_key_derivation(proof.shared_secret, rct::rct2sk(rct::I), derivation), error::wallet_internal_error, "Failed to generate key derivation"); crypto::public_key subaddr_spendkey; - crypto::derive_subaddress_public_key(out_key->key, derivation, proof.index_in_tx, subaddr_spendkey); + crypto::derive_subaddress_public_key(out_key_pub, derivation, proof.index_in_tx, subaddr_spendkey); THROW_WALLET_EXCEPTION_IF(subaddr_spendkeys.count(subaddr_spendkey) == 0, error::wallet_internal_error, "The address doesn't seem to have received the fund"); @@ -13953,7 +13960,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr amount = rct::h2d(ecdh_info.amount); } total += amount; - if (kispent_res["spent_status"][i]) + if (kispent_res["spent_status"][i].get() != 0) spent += amount; } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 16dda05212c..c92d2b95457 100755 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1362,7 +1362,10 @@ namespace tools for (size_t s = 0; s < cd.sources.size(); ++s) { - desc.amount_in += cd.sources[s].amount; + uint64_t new_amount_in = desc.amount_in + cd.sources[s].amount; + if (new_amount_in < desc.amount_in) + throw wallet_rpc_error{error_code::BAD_UNSIGNED_TX_DATA, "amount_in overflow"}; + desc.amount_in = new_amount_in; size_t ring_size = cd.sources[s].outputs.size(); if (ring_size < desc.ring_size) desc.ring_size = ring_size; @@ -1377,8 +1380,16 @@ namespace tools if (i == dests.end()) dests.insert(std::make_pair(entry.addr, std::make_pair(address, entry.amount))); else - i->second.second += entry.amount; - desc.amount_out += entry.amount; + { + uint64_t new_dest_amount = i->second.second + entry.amount; + if (new_dest_amount < i->second.second) + throw wallet_rpc_error{error_code::BAD_UNSIGNED_TX_DATA, "Destination amount overflow"}; + i->second.second = new_dest_amount; + } + uint64_t new_amount_out = desc.amount_out + entry.amount; + if (new_amount_out < desc.amount_out) + throw wallet_rpc_error{error_code::BAD_UNSIGNED_TX_DATA, "amount_out overflow"}; + desc.amount_out = new_amount_out; } if (cd.change_dts.amount > 0) { @@ -1395,7 +1406,10 @@ namespace tools if (memcmp(&cd.change_dts.addr, &cdn.change_dts.addr, sizeof(cd.change_dts.addr))) throw wallet_rpc_error{error_code::BAD_UNSIGNED_TX_DATA, "Change goes to more than one address"}; } - desc.change_amount += cd.change_dts.amount; + uint64_t new_change_amount = desc.change_amount + cd.change_dts.amount; + if (new_change_amount < desc.change_amount) + throw wallet_rpc_error{error_code::BAD_UNSIGNED_TX_DATA, "change_amount overflow"}; + desc.change_amount = new_change_amount; it->second.second -= cd.change_dts.amount; if (it->second.second == 0) dests.erase(cd.change_dts.addr); @@ -1419,6 +1433,8 @@ namespace tools desc.change_address = get_account_address_as_str(m_wallet->nettype(), cd0.subaddr_account > 0, cd0.change_dts.addr); } + if (desc.amount_in < desc.amount_out) + throw wallet_rpc_error{error_code::BAD_UNSIGNED_TX_DATA, "amount_in < amount_out"}; desc.fee = desc.amount_in - desc.amount_out; desc.unlock_time = cd.unlock_time; desc.extra = oxenc::to_hex(cd.extra.begin(), cd.extra.end()); @@ -2485,7 +2501,7 @@ namespace tools EDIT_ADDRESS_BOOK_ENTRY::response wallet_rpc_server::invoke(EDIT_ADDRESS_BOOK_ENTRY::request&& req) { require_open(); - + CHECK_IF_BACKGROUND_SYNCING(); const auto ab = m_wallet->get_address_book(); if (req.index >= ab.size())