diff --git a/nano/core_test/rpc.cpp b/nano/core_test/rpc.cpp index 903472dc..c48184a0 100644 --- a/nano/core_test/rpc.cpp +++ b/nano/core_test/rpc.cpp @@ -334,7 +334,7 @@ TEST (rpc, send_fail) ASSERT_NO_ERROR (system.poll ()); } done = true; - ASSERT_EQ (response.json.get ("error"), "Error generating block"); + ASSERT_EQ (response.json.get ("error"), "Account not found in wallet"); thread2.join (); } diff --git a/nano/node/rpc.cpp b/nano/node/rpc.cpp index 6d5fb2b0..63c5efaf 100644 --- a/nano/node/rpc.cpp +++ b/nano/node/rpc.cpp @@ -623,11 +623,7 @@ void nano::rpc_handler::account_representative_set () nano::account_info info; if (!node.store.account_get (transaction, account, info)) { - if (!nano::work_validate (info.head, work)) - { - wallet->store.work_put (transaction, account, work); - } - else + if (nano::work_validate (info.head, work)) { ec = nano::error_common::invalid_work; } @@ -644,6 +640,7 @@ void nano::rpc_handler::account_representative_set () } if (!ec) { + bool generate_work (work == 0); // Disable work generation if "work" option is provided auto response_a (response); wallet->change_async (account, representative, [response_a](std::shared_ptr block) { nano::block_hash hash (0); @@ -655,7 +652,7 @@ void nano::rpc_handler::account_representative_set () response_l.put ("block", hash.to_string ()); response_a (response_l); }, - work == 0); + work, generate_work); } } else @@ -2526,18 +2523,14 @@ void nano::rpc_handler::receive () { head = account; } - if (!nano::work_validate (head, work)) - { - auto transaction_a (node.store.tx_begin_write ()); - wallet->store.work_put (transaction_a, account, work); - } - else + if (nano::work_validate (head, work)) { ec = nano::error_common::invalid_work; } } if (!ec) { + bool generate_work (work == 0); // Disable work generation if "work" option is provided auto response_a (response); wallet->receive_async (std::move (block), account, nano::genesis_amount, [response_a](std::shared_ptr block_a) { nano::uint256_union hash_a (0); @@ -2549,7 +2542,7 @@ void nano::rpc_handler::receive () response_l.put ("block", hash_a.to_string ()); response_a (response_l); }, - work == 0); + work, generate_work); } } else @@ -2850,29 +2843,32 @@ void nano::rpc_handler::send () nano::uint128_t balance (0); if (!ec) { - auto transaction (node.wallets.tx_begin (work != 0)); // false if no "work" in request, true if work > 0 + auto transaction (node.wallets.tx_begin_read ()); auto block_transaction (node.store.tx_begin_read ()); if (wallet->store.valid_password (transaction)) { - nano::account_info info; - if (!node.store.account_get (block_transaction, source, info)) + if (wallet->store.find (transaction, source) != wallet->store.end ()) { - balance = (info.balance).number (); - } - else - { - ec = nano::error_common::account_not_found; - } - if (!ec && work) - { - if (!nano::work_validate (info.head, work)) + nano::account_info info; + if (!node.store.account_get (block_transaction, source, info)) { - wallet->store.work_put (transaction, source, work); + balance = (info.balance).number (); } else { - ec = nano::error_common::invalid_work; + ec = nano::error_common::account_not_found; } + if (!ec && work) + { + if (nano::work_validate (info.head, work)) + { + ec = nano::error_common::invalid_work; + } + } + } + else + { + ec = nano::error_common::account_not_found_wallet; } } else @@ -2882,6 +2878,7 @@ void nano::rpc_handler::send () } if (!ec) { + bool generate_work (work == 0); // Disable work generation if "work" option is provided boost::optional send_id (request.get_optional ("id")); auto rpc_l (shared_from_this ()); auto response_a (response); @@ -2906,7 +2903,7 @@ void nano::rpc_handler::send () } } }, - work == 0, send_id); + work, generate_work, send_id); } } else @@ -3537,7 +3534,7 @@ void nano::rpc_handler::wallet_representative_set () } for (auto & account : accounts) { - wallet->change_async (account, representative, [](std::shared_ptr) {}, false); + wallet->change_async (account, representative, [](std::shared_ptr) {}, 0, false); } } response_l.put ("set", "1"); diff --git a/nano/node/wallet.cpp b/nano/node/wallet.cpp index 65a252d7..1c8137e4 100644 --- a/nano/node/wallet.cpp +++ b/nano/node/wallet.cpp @@ -896,7 +896,7 @@ void nano::wallet_store::destroy (nano::transaction const & transaction_a) handle = 0; } -std::shared_ptr nano::wallet::receive_action (nano::block const & send_a, nano::account const & representative_a, nano::uint128_union const & amount_a, bool generate_work_a) +std::shared_ptr nano::wallet::receive_action (nano::block const & send_a, nano::account const & representative_a, nano::uint128_union const & amount_a, uint64_t work_a, bool generate_work_a) { nano::account account; auto hash (send_a.hash ()); @@ -914,19 +914,21 @@ std::shared_ptr nano::wallet::receive_action (nano::block const & s nano::raw_key prv; if (!store.fetch (transaction, account, prv)) { - uint64_t cached_work (0); - store.work_get (transaction, account, cached_work); + if (work_a == 0) + { + store.work_get (transaction, account, work_a); + } nano::account_info info; auto new_account (wallets.node.ledger.store.account_get (block_transaction, account, info)); if (!new_account) { std::shared_ptr rep_block = wallets.node.ledger.store.block_get (block_transaction, info.rep_block); assert (rep_block != nullptr); - block.reset (new nano::state_block (account, info.head, rep_block->representative (), info.balance.number () + pending_info.amount.number (), hash, prv, account, cached_work)); + block.reset (new nano::state_block (account, info.head, rep_block->representative (), info.balance.number () + pending_info.amount.number (), hash, prv, account, work_a)); } else { - block.reset (new nano::state_block (account, 0, representative_a, pending_info.amount, hash, prv, account, cached_work)); + block.reset (new nano::state_block (account, 0, representative_a, pending_info.amount, hash, prv, account, work_a)); } } else @@ -953,6 +955,7 @@ std::shared_ptr nano::wallet::receive_action (nano::block const & s { if (nano::work_validate (*block)) { + BOOST_LOG (wallets.node.log) << boost::str (boost::format ("Cached or provided work for block %1% account %2% is invalid, regenerating") % block->hash ().to_string () % account.to_account ()); wallets.node.work_generate_blocking (*block); } wallets.node.process_active (block); @@ -965,7 +968,7 @@ std::shared_ptr nano::wallet::receive_action (nano::block const & s return block; } -std::shared_ptr nano::wallet::change_action (nano::account const & source_a, nano::account const & representative_a, bool generate_work_a) +std::shared_ptr nano::wallet::change_action (nano::account const & source_a, nano::account const & representative_a, uint64_t work_a, bool generate_work_a) { std::shared_ptr block; { @@ -982,9 +985,11 @@ std::shared_ptr nano::wallet::change_action (nano::account const & nano::raw_key prv; auto error2 (store.fetch (transaction, source_a, prv)); assert (!error2); - uint64_t cached_work (0); - store.work_get (transaction, source_a, cached_work); - block.reset (new nano::state_block (source_a, info.head, representative_a, info.balance, 0, prv, source_a, cached_work)); + if (work_a == 0) + { + store.work_get (transaction, source_a, work_a); + } + block.reset (new nano::state_block (source_a, info.head, representative_a, info.balance, 0, prv, source_a, work_a)); } } } @@ -992,6 +997,7 @@ std::shared_ptr nano::wallet::change_action (nano::account const & { if (nano::work_validate (*block)) { + BOOST_LOG (wallets.node.log) << boost::str (boost::format ("Cached or provided work for block %1% account %2% is invalid, regenerating") % block->hash ().to_string () % source_a.to_account ()); wallets.node.work_generate_blocking (*block); } wallets.node.process_active (block); @@ -1004,7 +1010,7 @@ std::shared_ptr nano::wallet::change_action (nano::account const & return block; } -std::shared_ptr nano::wallet::send_action (nano::account const & source_a, nano::account const & account_a, nano::uint128_t const & amount_a, bool generate_work_a, boost::optional id_a) +std::shared_ptr nano::wallet::send_action (nano::account const & source_a, nano::account const & account_a, nano::uint128_t const & amount_a, uint64_t work_a, bool generate_work_a, boost::optional id_a) { std::shared_ptr block; boost::optional id_mdb_val; @@ -1054,9 +1060,11 @@ std::shared_ptr nano::wallet::send_action (nano::account const & so assert (!error2); std::shared_ptr rep_block = wallets.node.ledger.store.block_get (block_transaction, info.rep_block); assert (rep_block != nullptr); - uint64_t cached_work (0); - store.work_get (transaction, source_a, cached_work); - block.reset (new nano::state_block (source_a, info.head, rep_block->representative (), balance - amount_a, account_a, prv, source_a, cached_work)); + if (work_a == 0) + { + store.work_get (transaction, source_a, work_a); + } + block.reset (new nano::state_block (source_a, info.head, rep_block->representative (), balance - amount_a, account_a, prv, source_a, work_a)); if (id_mdb_val && block != nullptr) { auto status (mdb_put (wallets.env.tx (transaction), wallets.node.wallets.send_action_ids, *id_mdb_val, nano::mdb_val (block->hash ()), 0)); @@ -1075,6 +1083,7 @@ std::shared_ptr nano::wallet::send_action (nano::account const & so { if (nano::work_validate (*block)) { + BOOST_LOG (wallets.node.log) << boost::str (boost::format ("Cached or provided work for block %1% account %2% is invalid, regenerating") % block->hash ().to_string () % account_a.to_account ()); wallets.node.work_generate_blocking (*block); } wallets.node.process_active (block); @@ -1097,10 +1106,10 @@ bool nano::wallet::change_sync (nano::account const & source_a, nano::account co return result.get_future ().get (); } -void nano::wallet::change_async (nano::account const & source_a, nano::account const & representative_a, std::function)> const & action_a, bool generate_work_a) +void nano::wallet::change_async (nano::account const & source_a, nano::account const & representative_a, std::function)> const & action_a, uint64_t work_a, bool generate_work_a) { - wallets.node.wallets.queue_wallet_action (nano::wallets::high_priority, shared_from_this (), [source_a, representative_a, action_a, generate_work_a](nano::wallet & wallet_a) { - auto block (wallet_a.change_action (source_a, representative_a, generate_work_a)); + wallets.node.wallets.queue_wallet_action (nano::wallets::high_priority, shared_from_this (), [source_a, representative_a, action_a, work_a, generate_work_a](nano::wallet & wallet_a) { + auto block (wallet_a.change_action (source_a, representative_a, work_a, generate_work_a)); action_a (block); }); } @@ -1115,11 +1124,11 @@ bool nano::wallet::receive_sync (std::shared_ptr block_a, nano::acc return result.get_future ().get (); } -void nano::wallet::receive_async (std::shared_ptr block_a, nano::account const & representative_a, nano::uint128_t const & amount_a, std::function)> const & action_a, bool generate_work_a) +void nano::wallet::receive_async (std::shared_ptr block_a, nano::account const & representative_a, nano::uint128_t const & amount_a, std::function)> const & action_a, uint64_t work_a, bool generate_work_a) { //assert (dynamic_cast (block_a.get ()) != nullptr); - wallets.node.wallets.queue_wallet_action (amount_a, shared_from_this (), [block_a, representative_a, amount_a, action_a, generate_work_a](nano::wallet & wallet_a) { - auto block (wallet_a.receive_action (*static_cast (block_a.get ()), representative_a, amount_a, generate_work_a)); + wallets.node.wallets.queue_wallet_action (amount_a, shared_from_this (), [block_a, representative_a, amount_a, action_a, work_a, generate_work_a](nano::wallet & wallet_a) { + auto block (wallet_a.receive_action (*static_cast (block_a.get ()), representative_a, amount_a, work_a, generate_work_a)); action_a (block); }); } @@ -1134,10 +1143,10 @@ nano::block_hash nano::wallet::send_sync (nano::account const & source_a, nano:: return result.get_future ().get (); } -void nano::wallet::send_async (nano::account const & source_a, nano::account const & account_a, nano::uint128_t const & amount_a, std::function)> const & action_a, bool generate_work_a, boost::optional id_a) +void nano::wallet::send_async (nano::account const & source_a, nano::account const & account_a, nano::uint128_t const & amount_a, std::function)> const & action_a, uint64_t work_a, bool generate_work_a, boost::optional id_a) { - wallets.node.wallets.queue_wallet_action (nano::wallets::high_priority, shared_from_this (), [source_a, account_a, amount_a, action_a, generate_work_a, id_a](nano::wallet & wallet_a) { - auto block (wallet_a.send_action (source_a, account_a, amount_a, generate_work_a, id_a)); + wallets.node.wallets.queue_wallet_action (nano::wallets::high_priority, shared_from_this (), [source_a, account_a, amount_a, action_a, work_a, generate_work_a, id_a](nano::wallet & wallet_a) { + auto block (wallet_a.send_action (source_a, account_a, amount_a, work_a, generate_work_a, id_a)); action_a (block); }); } diff --git a/nano/node/wallet.hpp b/nano/node/wallet.hpp index d547bcf7..3f312ed2 100644 --- a/nano/node/wallet.hpp +++ b/nano/node/wallet.hpp @@ -119,9 +119,9 @@ class wallets; class wallet : public std::enable_shared_from_this { public: - std::shared_ptr change_action (nano::account const &, nano::account const &, bool = true); - std::shared_ptr receive_action (nano::block const &, nano::account const &, nano::uint128_union const &, bool = true); - std::shared_ptr send_action (nano::account const &, nano::account const &, nano::uint128_t const &, bool = true, boost::optional = {}); + std::shared_ptr change_action (nano::account const &, nano::account const &, uint64_t = 0, bool = true); + std::shared_ptr receive_action (nano::block const &, nano::account const &, nano::uint128_union const &, uint64_t = 0, bool = true); + std::shared_ptr send_action (nano::account const &, nano::account const &, nano::uint128_t const &, uint64_t = 0, bool = true, boost::optional = {}); wallet (bool &, nano::transaction &, nano::wallets &, std::string const &); wallet (bool &, nano::transaction &, nano::wallets &, std::string const &, std::string const &); void enter_initial_password (); @@ -136,11 +136,11 @@ public: bool import (std::string const &, std::string const &); void serialize (std::string &); bool change_sync (nano::account const &, nano::account const &); - void change_async (nano::account const &, nano::account const &, std::function)> const &, bool = true); + void change_async (nano::account const &, nano::account const &, std::function)> const &, uint64_t = 0, bool = true); bool receive_sync (std::shared_ptr, nano::account const &, nano::uint128_t const &); - void receive_async (std::shared_ptr, nano::account const &, nano::uint128_t const &, std::function)> const &, bool = true); + void receive_async (std::shared_ptr, nano::account const &, nano::uint128_t const &, std::function)> const &, uint64_t = 0, bool = true); nano::block_hash send_sync (nano::account const &, nano::account const &, nano::uint128_t const &); - void send_async (nano::account const &, nano::account const &, nano::uint128_t const &, std::function)> const &, bool = true, boost::optional = {}); + void send_async (nano::account const &, nano::account const &, nano::uint128_t const &, std::function)> const &, uint64_t = 0, bool = true, boost::optional = {}); void work_apply (nano::account const &, std::function); void work_cache_blocking (nano::account const &, nano::block_hash const &); void work_update (nano::transaction const &, nano::account const &, nano::block_hash const &, uint64_t);