From a44d94d390158a04db9bfd84bacd5ca1d7233ba0 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 5 Jan 2016 21:57:43 +0000 Subject: [PATCH 1/4] rpc: is_key_image_spent now checks the tx pool too --- src/rpc/core_rpc_server.cpp | 32 ++++++++++++++++++++++++- src/rpc/core_rpc_server_commands_defs.h | 6 +++++ src/wallet/wallet2.cpp | 6 ++--- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index e6973b0b8..021c12d6e 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -304,7 +304,37 @@ namespace cryptonote } res.spent_status.clear(); for (size_t n = 0; n < spent_status.size(); ++n) - res.spent_status.push_back(spent_status[n]); + res.spent_status.push_back(spent_status[n] ? COMMAND_RPC_IS_KEY_IMAGE_SPENT::SPENT_IN_BLOCKCHAIN : COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT); + + // check the pool too + std::vector txs; + std::vector ki; + r = m_core.get_pool_transactions_and_spent_keys_info(txs, ki); + if(!r) + { + res.status = "Failed"; + return true; + } + for (std::vector::const_iterator i = ki.begin(); i != ki.end(); ++i) + { + crypto::hash hash; + crypto::key_image spent_key_image; + if (parse_hash256(i->id_hash, hash)) + { + memcpy(&spent_key_image, &hash, sizeof(hash)); // a bit dodgy, should be other parse functions somewhere + for (size_t n = 0; n < res.spent_status.size(); ++n) + { + if (res.spent_status[n] == COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT) + { + if (key_images[n] == spent_key_image) + { + res.spent_status[n] = COMMAND_RPC_IS_KEY_IMAGE_SPENT::SPENT_IN_POOL; + break; + } + } + } + } + } 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 209378e5a..dcacffbb9 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -123,6 +123,12 @@ namespace cryptonote //----------------------------------------------- struct COMMAND_RPC_IS_KEY_IMAGE_SPENT { + enum STATUS { + UNSPENT = 0, + SPENT_IN_BLOCKCHAIN = 1, + SPENT_IN_POOL = 2, + }; + struct request { std::vector key_images; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index bceea367f..c6f287016 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1419,15 +1419,15 @@ void wallet2::rescan_spent() for (size_t i = 0; i < m_transfers.size(); ++i) { transfer_details& td = m_transfers[i]; - if (td.m_spent != daemon_resp.spent_status[i]) + if (td.m_spent != (daemon_resp.spent_status[i] != COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT)) { if (td.m_spent) { - LOG_PRINT_L1("Marking output " << i << " as unspent, it was marked as spent"); + LOG_PRINT_L0("Marking output " << i << "(" << td.m_key_image << ") as unspent, it was marked as spent"); } else { - LOG_PRINT_L1("Marking output " << i << " as spent, it was marked as unspent"); + LOG_PRINT_L0("Marking output " << i << "(" << td.m_key_image << ") as spent, it was marked as unspent"); } td.m_spent = daemon_resp.spent_status[i]; } From 67bbb56a6c577f3f1703a04b689896831afaa6e2 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 10 Jan 2016 11:56:13 +0000 Subject: [PATCH 2/4] wallet2: decide at runtime which upper tx size to use The value will be different depending on whether we've reached the first hard fork, which allows a larger size, or not. This fixes transactions being rejected by the daemon on mainnet where the first hard fork is not yet active. --- src/wallet/wallet2.cpp | 20 ++++++++++++++++---- src/wallet/wallet2.h | 6 ++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c6f287016..3edbaeca2 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1880,6 +1880,7 @@ void wallet2::transfer_selected(const std::vector bool @@ -2066,6 +2067,7 @@ std::vector wallet2::create_transactions_2(std::vector txes; bool adding_fee; // true if new outputs go towards fee, rather than destinations uint64_t needed_fee, available_for_fee = 0; + uint64_t upper_transaction_size_limit = get_upper_tranaction_size_limit(); // throw if attempting a transaction with no destinations THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination); @@ -2158,7 +2160,7 @@ std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector= TX_SIZE_TARGET(m_upper_transaction_size_limit)); + try_tx = dsts.empty() || (tx.selected_transfers.size() * (fake_outs_count+1) * APPROXIMATE_INPUT_BYTES >= TX_SIZE_TARGET(upper_transaction_size_limit)); } if (try_tx) { @@ -2290,6 +2292,8 @@ void wallet2::transfer_dust(size_t num_outputs, uint64_t unlock_time, uint64_t n { using namespace cryptonote; + uint64_t upper_transaction_size_limit = get_upper_tranaction_size_limit(); + // select all dust inputs for transaction // throw if there are none uint64_t money = 0; @@ -2354,7 +2358,7 @@ void wallet2::transfer_dust(size_t num_outputs, uint64_t unlock_time, uint64_t n crypto::secret_key tx_key; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); - THROW_WALLET_EXCEPTION_IF(m_upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, m_upper_transaction_size_limit); + THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); std::string key_images; bool all_are_txin_to_key = std::all_of(tx.vin.begin(), tx.vin.end(), [&](const txin_v& s_e) -> bool @@ -2409,6 +2413,14 @@ bool wallet2::use_fork_rules(uint8_t version) return close_enough; } //---------------------------------------------------------------------------------------------------- +uint64_t wallet2::get_upper_tranaction_size_limit() +{ + if (m_upper_transaction_size_limit > 0) + return m_upper_transaction_size_limit; + uint64_t full_reward_zone = use_fork_rules(2) ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1; + return ((full_reward_zone * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; +} +//---------------------------------------------------------------------------------------------------- std::vector wallet2::create_dust_sweep_transactions() { // From hard fork 1, we don't consider small amounts to be dust anymore diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 256154b4a..9912226c6 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -214,7 +214,7 @@ namespace tools // free block size. TODO: fix this so that it actually takes // into account the current median block size rather than // the minimum block size. - void init(const std::string& daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = ((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE); + void init(const std::string& daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = 0); bool deinit(); void stop() { m_run.store(false, std::memory_order_relaxed); } @@ -374,6 +374,7 @@ namespace tools void check_acc_out(const cryptonote::account_keys &acc, const cryptonote::tx_out &o, const crypto::public_key &tx_pub_key, size_t i, uint64_t &money_transfered, bool &error) const; void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const; bool use_fork_rules(uint8_t version); + uint64_t get_upper_tranaction_size_limit(); cryptonote::account_base m_account; std::string m_daemon_address; @@ -543,6 +544,7 @@ namespace tools // throw if attempting a transaction with no destinations THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination); + uint64_t upper_transaction_size_limit = get_upper_tranaction_size_limit(); uint64_t needed_money = fee; // calculate total amount being sent to all destinations @@ -664,7 +666,7 @@ namespace tools crypto::secret_key tx_key; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), sources, splitted_dsts, extra, tx, unlock_time, tx_key); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet); - THROW_WALLET_EXCEPTION_IF(m_upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, m_upper_transaction_size_limit); + THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit); std::string key_images; bool all_are_txin_to_key = std::all_of(tx.vin.begin(), tx.vin.end(), [&](const txin_v& s_e) -> bool From eaf4dcd7471302f8badaaca0deb509f715499a26 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 11 Jan 2016 21:50:41 +0000 Subject: [PATCH 3/4] daemon: fix status command when run from command line --- src/daemon/rpc_command_executor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 565623468..fc06c858b 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -277,7 +277,7 @@ bool t_rpc_command_executor::show_status() { { return true; } - if (!m_rpc_client->rpc_request(mreq, mres, "mining_status", fail_message.c_str())) + if (!m_rpc_client->rpc_request(mreq, mres, "/mining_status", fail_message.c_str())) { return true; } From 664dc42e18539d1222eb5007c1e0a74c84df20ef Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 11 Jan 2016 22:52:01 +0000 Subject: [PATCH 4/4] rpc: fix missing target information in RPC call which fixes the status command via RPC too. Turns out there are two versions of the GET_INFO call. I'd never noticed before. --- src/rpc/core_rpc_server.cpp | 2 ++ src/rpc/core_rpc_server_commands_defs.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 021c12d6e..0f9e2b3ab 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -902,6 +902,7 @@ namespace cryptonote res.height = m_core.get_current_blockchain_height(); res.target_height = m_core.get_target_blockchain_height(); res.difficulty = m_core.get_blockchain_storage().get_difficulty_for_next_block(); + res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET; res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase res.tx_pool_size = m_core.get_pool_transactions_count(); res.alt_blocks_count = m_core.get_blockchain_storage().get_alternative_blocks_count(); @@ -910,6 +911,7 @@ namespace cryptonote res.incoming_connections_count = total_conn - res.outgoing_connections_count; res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count(); res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); + res.testnet = m_testnet; 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 dcacffbb9..772d1d942 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -295,6 +295,7 @@ namespace cryptonote KV_SERIALIZE(height) KV_SERIALIZE(target_height) KV_SERIALIZE(difficulty) + KV_SERIALIZE(target) KV_SERIALIZE(tx_count) KV_SERIALIZE(tx_pool_size) KV_SERIALIZE(alt_blocks_count)