diff --git a/rai/core_test/rpc.cpp b/rai/core_test/rpc.cpp index b771914f..320aded6 100644 --- a/rai/core_test/rpc.cpp +++ b/rai/core_test/rpc.cpp @@ -379,7 +379,6 @@ TEST (rpc, wallet_add) rai::keypair key1; std::string key_text; key1.prv.data.encode_hex (key_text); - system.wallet (0)->insert_adhoc (key1.prv); boost::property_tree::ptree request; std::string wallet; system.nodes[0]->wallets.items.begin ()->first.encode_hex (wallet); @@ -394,6 +393,7 @@ TEST (rpc, wallet_add) ASSERT_EQ (200, response.status); std::string account_text1 (response.json.get ("account")); ASSERT_EQ (account_text1, key1.pub.to_account ()); + ASSERT_TRUE (system.wallet (0)->exists (key1.pub)); } TEST (rpc, wallet_password_valid) @@ -1318,6 +1318,8 @@ TEST (rpc, pending) rai::uint128_union amount; amount.decode_dec (i->second.get ("")); blocks[hash] = amount; + boost::optional source (i->second.get_optional ("source")); + ASSERT_FALSE (source.is_initialized ()); } ASSERT_EQ (blocks[block1->hash ()], 100); request.put ("threshold", "101"); @@ -2246,6 +2248,8 @@ TEST (rpc, accounts_pending) rai::uint128_union amount; amount.decode_dec (i->second.get ("")); blocks[hash] = amount; + boost::optional source (i->second.get_optional ("source")); + ASSERT_FALSE (source.is_initialized ()); } } ASSERT_EQ (blocks[block1->hash ()], 100); @@ -2446,6 +2450,8 @@ TEST (rpc, wallet_pending) rai::uint128_union amount; amount.decode_dec (i->second.get ("")); blocks[hash] = amount; + boost::optional source (i->second.get_optional ("source")); + ASSERT_FALSE (source.is_initialized ()); } } ASSERT_EQ (blocks[block1->hash ()], 100); @@ -2761,6 +2767,27 @@ TEST (rpc, account_info) ASSERT_TRUE (time - stol (modified_timestamp) < 5); std::string block_count (response.json.get ("block_count")); ASSERT_EQ ("2", block_count); + boost::optional weight (response.json.get_optional ("weight")); + ASSERT_FALSE (weight.is_initialized ()); + boost::optional pending (response.json.get_optional ("pending")); + ASSERT_FALSE (pending.is_initialized ()); + boost::optional representative (response.json.get_optional ("representative")); + ASSERT_FALSE (representative.is_initialized ()); + // Test for optional values + request.put ("weight", "true"); + request.put ("pending", "1"); + request.put ("representative", "1"); + test_response response2 (request, rpc, system.service); + while (response2.status == 0) + { + system.poll (); + } + std::string weight2 (response2.json.get ("weight")); + ASSERT_EQ ("100", weight2); + std::string pending2 (response2.json.get ("pending")); + ASSERT_EQ ("0", pending2); + std::string representative2 (response2.json.get ("representative")); + ASSERT_EQ (rai::test_genesis_key.pub.to_account (), representative2); } TEST (rpc, blocks_info) @@ -2791,6 +2818,26 @@ TEST (rpc, blocks_info) ASSERT_EQ (rai::genesis_amount.convert_to (), amount_text); std::string blocks_text (blocks.second.get ("contents")); ASSERT_FALSE (blocks_text.empty ()); + boost::optional pending (blocks.second.get_optional ("pending")); + ASSERT_FALSE (pending.is_initialized ()); + boost::optional source (blocks.second.get_optional ("source_account")); + ASSERT_FALSE (source.is_initialized ()); + } + // Test for optional values + request.put ("source", "true"); + request.put ("pending", "1"); + test_response response2 (request, rpc, system.service); + while (response2.status == 0) + { + system.poll (); + } + ASSERT_EQ (200, response2.status); + for (auto & blocks : response2.json.get_child ("blocks")) + { + std::string source (blocks.second.get ("source_account")); + ASSERT_EQ ("0", source); + std::string pending (blocks.second.get ("pending")); + ASSERT_EQ ("0", pending); } } @@ -2919,6 +2966,33 @@ TEST (rpc, ledger) ASSERT_EQ (std::to_string (time), modified_timestamp); std::string block_count (accounts.second.get ("block_count")); ASSERT_EQ ("1", block_count); + boost::optional weight (accounts.second.get_optional ("weight")); + ASSERT_FALSE (weight.is_initialized ()); + boost::optional pending (accounts.second.get_optional ("pending")); + ASSERT_FALSE (pending.is_initialized ()); + boost::optional representative (accounts.second.get_optional ("representative")); + ASSERT_FALSE (representative.is_initialized ()); + } + // Test for optional values + request.put ("weight", "1"); + request.put ("pending", "1"); + request.put ("representative", "true"); + test_response response2 (request, rpc, system.service); + while (response2.status == 0) + { + system.poll (); + } + for (auto & accounts : response2.json.get_child ("accounts")) + { + boost::optional weight (accounts.second.get_optional ("weight")); + ASSERT_TRUE (weight.is_initialized ()); + ASSERT_EQ ("0", weight.get ()); + boost::optional pending (accounts.second.get_optional ("pending")); + ASSERT_TRUE (pending.is_initialized ()); + ASSERT_EQ ("0", pending.get ()); + boost::optional representative (accounts.second.get_optional ("representative")); + ASSERT_TRUE (representative.is_initialized ()); + ASSERT_EQ (rai::test_genesis_key.pub.to_account (), representative.get ()); } } @@ -3135,3 +3209,99 @@ TEST (rpc, wallet_create_fail) } ASSERT_EQ ("Failed to create wallet. Increase lmdb_max_dbs in node config.", response.json.get ("error")); } + +TEST (rpc, wallet_ledger) +{ + rai::system system (24000, 1); + rai::keypair key; + rai::genesis genesis; + system.wallet (0)->insert_adhoc (key.prv); + auto & node1 (*system.nodes[0]); + auto latest (system.nodes[0]->latest (rai::test_genesis_key.pub)); + rai::send_block send (latest, key.pub, 100, rai::test_genesis_key.prv, rai::test_genesis_key.pub, node1.generate_work (latest)); + system.nodes[0]->process (send); + rai::open_block open (send.hash (), rai::test_genesis_key.pub, key.pub, key.prv, key.pub, node1.generate_work (key.pub)); + ASSERT_EQ (rai::process_result::progress, system.nodes[0]->process (open).code); + auto time (rai::seconds_since_epoch ()); + rai::rpc rpc (system.service, *system.nodes[0], rai::rpc_config (true)); + rpc.start (); + boost::property_tree::ptree request; + request.put ("action", "wallet_ledger"); + request.put ("wallet", system.nodes[0]->wallets.items.begin ()->first.to_string ()); + request.put ("sorting", "1"); + request.put ("count", "1"); + test_response response (request, rpc, system.service); + while (response.status == 0) + { + system.poll (); + } + for (auto & accounts : response.json.get_child ("accounts")) + { + std::string account_text (accounts.first); + ASSERT_EQ (key.pub.to_account (), account_text); + std::string frontier (accounts.second.get ("frontier")); + ASSERT_EQ (open.hash ().to_string (), frontier); + std::string open_block (accounts.second.get ("open_block")); + ASSERT_EQ (open.hash ().to_string (), open_block); + std::string representative_block (accounts.second.get ("representative_block")); + ASSERT_EQ (open.hash ().to_string (), representative_block); + std::string balance_text (accounts.second.get ("balance")); + ASSERT_EQ ("340282366920938463463374607431768211355", balance_text); + std::string modified_timestamp (accounts.second.get ("modified_timestamp")); + ASSERT_EQ (std::to_string (time), modified_timestamp); + std::string block_count (accounts.second.get ("block_count")); + ASSERT_EQ ("1", block_count); + boost::optional weight (accounts.second.get_optional ("weight")); + ASSERT_FALSE (weight.is_initialized ()); + boost::optional pending (accounts.second.get_optional ("pending")); + ASSERT_FALSE (pending.is_initialized ()); + boost::optional representative (accounts.second.get_optional ("representative")); + ASSERT_FALSE (representative.is_initialized ()); + } + // Test for optional values + request.put ("weight", "true"); + request.put ("pending", "1"); + request.put ("representative", "false"); + test_response response2 (request, rpc, system.service); + while (response2.status == 0) + { + system.poll (); + } + for (auto & accounts : response2.json.get_child ("accounts")) + { + boost::optional weight (accounts.second.get_optional ("weight")); + ASSERT_TRUE (weight.is_initialized ()); + ASSERT_EQ ("0", weight.get ()); + boost::optional pending (accounts.second.get_optional ("pending")); + ASSERT_TRUE (pending.is_initialized ()); + ASSERT_EQ ("0", pending.get ()); + boost::optional representative (accounts.second.get_optional ("representative")); + ASSERT_FALSE (representative.is_initialized ()); + } +} + +TEST (rpc, wallet_add_watch) +{ + rai::system system (24000, 1); + rai::rpc rpc (system.service, *system.nodes[0], rai::rpc_config (true)); + rpc.start (); + boost::property_tree::ptree request; + std::string wallet; + system.nodes[0]->wallets.items.begin ()->first.encode_hex (wallet); + request.put ("wallet", wallet); + request.put ("action", "wallet_add_watch"); + boost::property_tree::ptree entry; + boost::property_tree::ptree peers_l; + entry.put ("", rai::test_genesis_key.pub.to_account ()); + peers_l.push_back (std::make_pair ("", entry)); + request.add_child ("accounts", peers_l); + test_response response (request, rpc, system.service); + while (response.status == 0) + { + system.poll (); + } + ASSERT_EQ (200, response.status); + std::string success (response.json.get ("success")); + ASSERT_TRUE (success.empty ()); + ASSERT_TRUE (system.wallet (0)->exists (rai::test_genesis_key.pub)); +} diff --git a/rai/node/rpc.cpp b/rai/node/rpc.cpp index bb8290b5..a8096926 100644 --- a/rai/node/rpc.cpp +++ b/rai/node/rpc.cpp @@ -282,12 +282,7 @@ void rai::rpc_handler::account_create () auto existing (node.wallets.items.find (wallet)); if (existing != node.wallets.items.end ()) { - bool generate_work (true); - boost::optional work (request.get_optional ("work")); - if (work.is_initialized ()) - { - generate_work = work.get (); - } + const bool generate_work = request.get ("work", true); rai::account new_key (existing->second->deterministic_insert (generate_work)); if (!new_key.is_zero ()) { @@ -340,24 +335,9 @@ void rai::rpc_handler::account_info () auto error (account.decode_account (account_text)); if (!error) { - bool representative (false); - boost::optional representative_optional (request.get_optional ("representative")); - if (representative_optional.is_initialized ()) - { - representative = representative_optional.get (); - } - bool weight (false); - boost::optional weight_optional (request.get_optional ("weight")); - if (weight_optional.is_initialized ()) - { - weight = weight_optional.get (); - } - bool pending (false); - boost::optional pending_optional (request.get_optional ("pending")); - if (pending_optional.is_initialized ()) - { - pending = pending_optional.get (); - } + const bool representative = request.get ("representative", false); + const bool weight = request.get ("weight", false); + const bool pending = request.get ("pending", false); rai::transaction transaction (node.store.environment, nullptr, false); rai::account_info info; if (!node.store.account_get (transaction, account, info)) @@ -742,12 +722,7 @@ void rai::rpc_handler::accounts_create () auto existing (node.wallets.items.find (wallet)); if (existing != node.wallets.items.end ()) { - bool generate_work (true); - boost::optional work (request.get_optional ("work")); - if (work.is_initialized ()) - { - generate_work = work.get (); - } + const bool generate_work = request.get ("work", true); boost::property_tree::ptree response_l; boost::property_tree::ptree accounts; for (auto i (0); accounts.size () < count; ++i) @@ -815,7 +790,6 @@ void rai::rpc_handler::accounts_pending () { uint64_t count (std::numeric_limits::max ()); rai::uint128_union threshold (0); - bool source (false); boost::optional count_text (request.get_optional ("count")); if (count_text.is_initialized ()) { @@ -834,11 +808,7 @@ void rai::rpc_handler::accounts_pending () error_response (response, "Bad threshold number"); } } - boost::optional source_optional (request.get_optional ("source")); - if (source_optional.is_initialized ()) - { - source = source_optional.get (); - } + const bool source = request.get ("source", false); boost::property_tree::ptree response_l; boost::property_tree::ptree pending; rai::transaction transaction (node.store.environment, nullptr, false); @@ -965,18 +935,8 @@ void rai::rpc_handler::blocks () void rai::rpc_handler::blocks_info () { - bool pending (false); - boost::optional pending_optional (request.get_optional ("pending")); - if (pending_optional.is_initialized ()) - { - pending = pending_optional.get (); - } - bool source (false); - boost::optional source_optional (request.get_optional ("source")); - if (source_optional.is_initialized ()) - { - source = source_optional.get (); - } + const bool pending = request.get ("pending", false); + const bool source = request.get ("source", false); std::vector hashes; boost::property_tree::ptree response_l; boost::property_tree::ptree blocks; @@ -1792,7 +1752,6 @@ void rai::rpc_handler::ledger () { rai::account start (0); uint64_t count (std::numeric_limits::max ()); - bool sorting (false); boost::optional account_text (request.get_optional ("account")); if (account_text.is_initialized ()) { @@ -1811,29 +1770,16 @@ void rai::rpc_handler::ledger () error_response (response, "Invalid count limit"); } } - boost::optional sorting_optional (request.get_optional ("sorting")); - if (sorting_optional.is_initialized ()) + uint64_t modified_since (0); + boost::optional modified_since_text (request.get_optional ("modified_since")); + if (modified_since_text.is_initialized ()) { - sorting = sorting_optional.get (); - } - bool representative (false); - boost::optional representative_optional (request.get_optional ("representative")); - if (representative_optional.is_initialized ()) - { - representative = representative_optional.get (); - } - bool weight (false); - boost::optional weight_optional (request.get_optional ("weight")); - if (weight_optional.is_initialized ()) - { - weight = weight_optional.get (); - } - bool pending (false); - boost::optional pending_optional (request.get_optional ("pending")); - if (pending_optional.is_initialized ()) - { - pending = pending_optional.get (); + modified_since = strtoul (modified_since_text.get ().c_str (), NULL, 10); } + const bool sorting = request.get ("sorting", false); + const bool representative = request.get ("representative", false); + const bool weight = request.get ("weight", false); + const bool pending = request.get ("pending", false); boost::property_tree::ptree response_a; boost::property_tree::ptree response_l; boost::property_tree::ptree accounts; @@ -1843,33 +1789,36 @@ void rai::rpc_handler::ledger () for (auto i (node.store.latest_begin (transaction, start)), n (node.store.latest_end ()); i != n && accounts.size () < count; ++i) { rai::account_info info (i->second); - rai::account account (i->first.uint256 ()); - boost::property_tree::ptree response_l; - response_l.put ("frontier", info.head.to_string ()); - response_l.put ("open_block", info.open_block.to_string ()); - response_l.put ("representative_block", info.rep_block.to_string ()); - std::string balance; - rai::uint128_union (info.balance).encode_dec (balance); - response_l.put ("balance", balance); - response_l.put ("modified_timestamp", std::to_string (info.modified)); - response_l.put ("block_count", std::to_string (info.block_count)); - if (representative) + if (info.modified >= modified_since) { - auto block (node.store.block_get (transaction, info.rep_block)); - assert (block != nullptr); - response_l.put ("representative", block->representative ().to_account ()); + rai::account account (i->first.uint256 ()); + boost::property_tree::ptree response_l; + response_l.put ("frontier", info.head.to_string ()); + response_l.put ("open_block", info.open_block.to_string ()); + response_l.put ("representative_block", info.rep_block.to_string ()); + std::string balance; + rai::uint128_union (info.balance).encode_dec (balance); + response_l.put ("balance", balance); + response_l.put ("modified_timestamp", std::to_string (info.modified)); + response_l.put ("block_count", std::to_string (info.block_count)); + if (representative) + { + auto block (node.store.block_get (transaction, info.rep_block)); + assert (block != nullptr); + response_l.put ("representative", block->representative ().to_account ()); + } + if (weight) + { + auto account_weight (node.ledger.weight (transaction, account)); + response_l.put ("weight", account_weight.convert_to ()); + } + if (pending) + { + auto account_pending (node.ledger.account_pending (transaction, account)); + response_l.put ("pending", account_pending.convert_to ()); + } + accounts.push_back (std::make_pair (account.to_account (), response_l)); } - if (weight) - { - auto account_weight (node.ledger.weight (transaction, account)); - response_l.put ("weight", account_weight.convert_to ()); - } - if (pending) - { - auto account_pending (node.ledger.account_pending (transaction, account)); - response_l.put ("pending", account_pending.convert_to ()); - } - accounts.push_back (std::make_pair (account.to_account (), response_l)); } } else // Sorting @@ -1877,8 +1826,12 @@ void rai::rpc_handler::ledger () std::vector> ledger_l; for (auto i (node.store.latest_begin (transaction, start)), n (node.store.latest_end ()); i != n; ++i) { - rai::uint128_union balance (rai::account_info (i->second).balance); - ledger_l.push_back (std::make_pair (balance, rai::account (i->first.uint256 ()))); + rai::account_info info (i->second); + rai::uint128_union balance (info.balance); + if (info.modified >= modified_since) + { + ledger_l.push_back (std::make_pair (balance, rai::account (i->first.uint256 ()))); + } } std::sort (ledger_l.begin (), ledger_l.end ()); std::reverse (ledger_l.begin (), ledger_l.end ()); @@ -2124,7 +2077,6 @@ void rai::rpc_handler::pending () { uint64_t count (std::numeric_limits::max ()); rai::uint128_union threshold (0); - bool source (false); boost::optional count_text (request.get_optional ("count")); if (count_text.is_initialized ()) { @@ -2143,11 +2095,7 @@ void rai::rpc_handler::pending () error_response (response, "Bad threshold number"); } } - boost::optional source_optional (request.get_optional ("source")); - if (source_optional.is_initialized ()) - { - source = source_optional.get (); - } + const bool source = request.get ("source", false); boost::property_tree::ptree response_l; boost::property_tree::ptree peers_l; { @@ -2711,7 +2659,6 @@ void rai::rpc_handler::receive_minimum_set () void rai::rpc_handler::representatives () { uint64_t count (std::numeric_limits::max ()); - bool sorting (false); boost::optional count_text (request.get_optional ("count")); if (count_text.is_initialized ()) { @@ -2721,11 +2668,7 @@ void rai::rpc_handler::representatives () error_response (response, "Invalid count limit"); } } - boost::optional sorting_optional (request.get_optional ("sorting")); - if (sorting_optional.is_initialized ()) - { - sorting = sorting_optional.get (); - } + const bool sorting = request.get ("sorting", false); boost::property_tree::ptree response_l; boost::property_tree::ptree representatives; rai::transaction transaction (node.store.environment, nullptr, false); @@ -3216,12 +3159,7 @@ void rai::rpc_handler::wallet_add () auto existing (node.wallets.items.find (wallet)); if (existing != node.wallets.items.end ()) { - bool generate_work (true); - boost::optional work (request.get_optional ("work")); - if (work.is_initialized ()) - { - generate_work = work.get (); - } + const bool generate_work = request.get ("work", true); auto pub (existing->second->insert_adhoc (key, generate_work)); if (!pub.is_zero ()) { @@ -3255,6 +3193,60 @@ void rai::rpc_handler::wallet_add () } } +void rai::rpc_handler::wallet_add_watch () +{ + if (rpc.config.enable_control) + { + std::string wallet_text (request.get ("wallet")); + rai::uint256_union wallet; + auto error (wallet.decode_hex (wallet_text)); + if (!error) + { + auto existing (node.wallets.items.find (wallet)); + if (existing != node.wallets.items.end ()) + { + rai::transaction transaction (node.store.environment, nullptr, true); + if (existing->second->store.valid_password (transaction)) + { + for (auto & accounts : request.get_child ("accounts")) + { + std::string account_text = accounts.second.data (); + rai::uint256_union account; + auto error (account.decode_account (account_text)); + if (!error) + { + existing->second->insert_watch (transaction, account); + } + else + { + error_response (response, "Bad account number"); + } + } + boost::property_tree::ptree response_l; + response_l.put ("success", ""); + response (response_l); + } + else + { + error_response (response, "Wallet locked"); + } + } + else + { + error_response (response, "Wallet not found"); + } + } + else + { + error_response (response, "Bad wallet number"); + } + } + else + { + error_response (response, "RPC control is disabled"); + } +} + void rai::rpc_handler::wallet_balance_total () { std::string wallet_text (request.get ("wallet")); @@ -3587,6 +3579,79 @@ void rai::rpc_handler::wallet_key_valid () } } +void rai::rpc_handler::wallet_ledger () +{ + const bool representative = request.get ("representative", false); + const bool weight = request.get ("weight", false); + const bool pending = request.get ("pending", false); + uint64_t modified_since (0); + boost::optional modified_since_text (request.get_optional ("modified_since")); + if (modified_since_text.is_initialized ()) + { + modified_since = strtoul (modified_since_text.get ().c_str (), NULL, 10); + } + std::string wallet_text (request.get ("wallet")); + rai::uint256_union wallet; + auto error (wallet.decode_hex (wallet_text)); + if (!error) + { + auto existing (node.wallets.items.find (wallet)); + if (existing != node.wallets.items.end ()) + { + boost::property_tree::ptree response_l; + boost::property_tree::ptree accounts; + rai::transaction transaction (node.store.environment, nullptr, false); + for (auto i (existing->second->store.begin (transaction)), n (existing->second->store.end ()); i != n; ++i) + { + rai::account account (i->first.uint256 ()); + rai::account_info info; + if (!node.store.account_get (transaction, account, info)) + { + if (info.modified >= modified_since) + { + boost::property_tree::ptree entry; + entry.put ("frontier", info.head.to_string ()); + entry.put ("open_block", info.open_block.to_string ()); + entry.put ("representative_block", info.rep_block.to_string ()); + std::string balance; + rai::uint128_union (info.balance).encode_dec (balance); + entry.put ("balance", balance); + entry.put ("modified_timestamp", std::to_string (info.modified)); + entry.put ("block_count", std::to_string (info.block_count)); + if (representative) + { + auto block (node.store.block_get (transaction, info.rep_block)); + assert (block != nullptr); + entry.put ("representative", block->representative ().to_account ()); + } + if (weight) + { + auto account_weight (node.ledger.weight (transaction, account)); + entry.put ("weight", account_weight.convert_to ()); + } + if (pending) + { + auto account_pending (node.ledger.account_pending (transaction, account)); + entry.put ("pending", account_pending.convert_to ()); + } + accounts.push_back (std::make_pair (account.to_account (), entry)); + } + } + } + response_l.add_child ("accounts", accounts); + response (response_l); + } + else + { + error_response (response, "Wallet not found"); + } + } + else + { + error_response (response, "Bad wallet number"); + } +} + void rai::rpc_handler::wallet_lock () { if (rpc.config.enable_control) @@ -3634,7 +3699,6 @@ void rai::rpc_handler::wallet_pending () { uint64_t count (std::numeric_limits::max ()); rai::uint128_union threshold (0); - bool source (false); boost::optional count_text (request.get_optional ("count")); if (count_text.is_initialized ()) { @@ -3653,11 +3717,7 @@ void rai::rpc_handler::wallet_pending () error_response (response, "Bad threshold number"); } } - boost::optional source_optional (request.get_optional ("source")); - if (source_optional.is_initialized ()) - { - source = source_optional.get (); - } + const bool source = request.get ("source", false); boost::property_tree::ptree response_l; boost::property_tree::ptree pending; rai::transaction transaction (node.store.environment, nullptr, false); @@ -4554,6 +4614,10 @@ void rai::rpc_handler::process_request () { wallet_add (); } + else if (action == "wallet_add_watch") + { + wallet_add_watch (); + } else if (action == "wallet_balance_total") { wallet_balance_total (); @@ -4590,6 +4654,10 @@ void rai::rpc_handler::process_request () { wallet_key_valid (); } + else if (action == "wallet_ledger") + { + wallet_ledger (); + } else if (action == "wallet_lock") { wallet_lock (); diff --git a/rai/node/rpc.hpp b/rai/node/rpc.hpp index 2bf0b6f9..91ca8a39 100644 --- a/rai/node/rpc.hpp +++ b/rai/node/rpc.hpp @@ -185,6 +185,7 @@ public: void validate_account_number (); void version (); void wallet_add (); + void wallet_add_watch (); void wallet_balance_total (); void wallet_balances (); void wallet_change_seed (); @@ -194,6 +195,7 @@ public: void wallet_export (); void wallet_frontiers (); void wallet_key_valid (); + void wallet_ledger (); void wallet_lock (); void wallet_pending (); void wallet_representative (); diff --git a/rai/node/wallet.cpp b/rai/node/wallet.cpp index e48bab37..2518bc85 100644 --- a/rai/node/wallet.cpp +++ b/rai/node/wallet.cpp @@ -420,6 +420,11 @@ rai::public_key rai::wallet_store::insert_adhoc (MDB_txn * transaction_a, rai::r return pub; } +void rai::wallet_store::insert_watch (MDB_txn * transaction_a, rai::public_key const & pub) +{ + entry_put_raw (transaction_a, pub, rai::wallet_value (rai::uint256_union (0), 0)); +} + void rai::wallet_store::erase (MDB_txn * transaction_a, rai::public_key const & pub) { auto status (mdb_del (transaction_a, handle, rai::mdb_val (pub), nullptr)); @@ -790,6 +795,11 @@ rai::public_key rai::wallet::insert_adhoc (rai::raw_key const & account_a, bool return result; } +void rai::wallet::insert_watch (MDB_txn * transaction_a, rai::public_key const & pub_a) +{ + store.insert_watch (transaction_a, pub_a); +} + bool rai::wallet::exists (rai::public_key const & account_a) { rai::transaction transaction (store.environment, nullptr, false); @@ -1118,7 +1128,11 @@ public: { for (auto i (wallet_a->store.begin (transaction_a)), n (wallet_a->store.end ()); i != n; ++i) { - keys.insert (i->first.uint256 ()); + // Don't search pending for watch-only accounts + if (!rai::wallet_value (i->second).key.is_zero ()) + { + keys.insert (i->first.uint256 ()); + } } } void run () diff --git a/rai/node/wallet.hpp b/rai/node/wallet.hpp index 0bcc7d8a..3de60d60 100644 --- a/rai/node/wallet.hpp +++ b/rai/node/wallet.hpp @@ -74,6 +74,7 @@ public: rai::account representative (MDB_txn *); void representative_set (MDB_txn *, rai::account const &); rai::public_key insert_adhoc (MDB_txn *, rai::raw_key const &); + void insert_watch (MDB_txn *, rai::public_key const &); void erase (MDB_txn *, rai::public_key const &); rai::wallet_value entry_get_raw (MDB_txn *, rai::public_key const &); void entry_put_raw (MDB_txn *, rai::public_key const &, rai::wallet_value const &); @@ -132,6 +133,7 @@ public: bool enter_password (std::string const &); rai::public_key insert_adhoc (rai::raw_key const &, bool = true); rai::public_key insert_adhoc (MDB_txn *, rai::raw_key const &, bool = true); + void insert_watch (MDB_txn *, rai::public_key const &); rai::public_key deterministic_insert (MDB_txn *, bool = true); rai::public_key deterministic_insert (bool = true); bool exists (rai::public_key const &);