From 28115facb3299f7aef58aef15a84d3104d04d2f6 Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Mon, 7 Jan 2019 16:10:46 +0000 Subject: [PATCH] Optional deterministic index in RPC account_create (#1547) --- nano/core_test/rpc.cpp | 36 +++++++++++++++++++++++++++++------- nano/node/rpc.cpp | 29 +++++++++++++++++++++++++---- nano/node/wallet.cpp | 27 +++++++++++++++++++++++++++ nano/node/wallet.hpp | 2 ++ 4 files changed, 83 insertions(+), 11 deletions(-) diff --git a/nano/core_test/rpc.cpp b/nano/core_test/rpc.cpp index 5b3d31261..ab550b49f 100644 --- a/nano/core_test/rpc.cpp +++ b/nano/core_test/rpc.cpp @@ -123,17 +123,39 @@ TEST (rpc, account_create) boost::property_tree::ptree request; request.put ("action", "account_create"); request.put ("wallet", system.nodes[0]->wallets.items.begin ()->first.to_string ()); - test_response response (request, rpc, system.io_ctx); + test_response response0 (request, rpc, system.io_ctx); system.deadline_set (5s); - while (response.status == 0) + while (response0.status == 0) { ASSERT_NO_ERROR (system.poll ()); } - ASSERT_EQ (200, response.status); - auto account_text (response.json.get ("account")); - nano::uint256_union account; - ASSERT_FALSE (account.decode_account (account_text)); - ASSERT_TRUE (system.wallet (0)->exists (account)); + ASSERT_EQ (200, response0.status); + auto account_text0 (response0.json.get ("account")); + nano::uint256_union account0; + ASSERT_FALSE (account0.decode_account (account_text0)); + ASSERT_TRUE (system.wallet (0)->exists (account0)); + uint64_t max_index (std::numeric_limits::max ()); + request.put ("index", max_index); + test_response response1 (request, rpc, system.io_ctx); + system.deadline_set (5s); + while (response1.status == 0) + { + ASSERT_NO_ERROR (system.poll ()); + } + ASSERT_EQ (200, response1.status); + auto account_text1 (response1.json.get ("account")); + nano::uint256_union account1; + ASSERT_FALSE (account1.decode_account (account_text1)); + ASSERT_TRUE (system.wallet (0)->exists (account1)); + request.put ("index", max_index + 1); + test_response response2 (request, rpc, system.io_ctx); + system.deadline_set (5s); + while (response2.status == 0) + { + ASSERT_NO_ERROR (system.poll ()); + } + ASSERT_EQ (200, response2.status); + ASSERT_EQ (response2.json.get ("error"), "Invalid index"); } TEST (rpc, account_weight) diff --git a/nano/node/rpc.cpp b/nano/node/rpc.cpp index 4e649f362..ba9d7514f 100644 --- a/nano/node/rpc.cpp +++ b/nano/node/rpc.cpp @@ -427,14 +427,35 @@ void nano::rpc_handler::account_create () if (!ec) { const bool generate_work = request.get ("work", true); - nano::account new_key (wallet->deterministic_insert (generate_work)); - if (!new_key.is_zero ()) + nano::account new_key; + auto index_text (request.get_optional ("index")); + if (index_text.is_initialized ()) { - response_l.put ("account", new_key.to_account ()); + uint64_t index; + if (decode_unsigned (index_text.get (), index) || index > static_cast (std::numeric_limits::max ())) + { + ec = nano::error_common::invalid_index; + } + else + { + new_key = wallet->deterministic_insert (static_cast (index), generate_work); + } } else { - ec = nano::error_common::wallet_locked; + new_key = wallet->deterministic_insert (generate_work); + } + + if (!ec) + { + if (!new_key.is_zero ()) + { + response_l.put ("account", new_key.to_account ()); + } + else + { + ec = nano::error_common::wallet_locked; + } } } response_errors (); diff --git a/nano/node/wallet.cpp b/nano/node/wallet.cpp index dbc398e61..6cf3b0453 100644 --- a/nano/node/wallet.cpp +++ b/nano/node/wallet.cpp @@ -75,6 +75,18 @@ nano::public_key nano::wallet_store::deterministic_insert (nano::transaction con return result; } +nano::public_key nano::wallet_store::deterministic_insert (nano::transaction const & transaction_a, uint32_t const index) +{ + nano::raw_key prv; + deterministic_key (prv, transaction_a, index); + nano::public_key result (nano::pub_key (prv.data)); + uint64_t marker (1); + marker <<= 32; + marker |= index; + entry_put_raw (transaction_a, result, nano::wallet_value (nano::uint256_union (marker), 0)); + return result; +} + void nano::wallet_store::deterministic_key (nano::raw_key & prv_a, nano::transaction const & transaction_a, uint32_t index_a) { assert (valid_password (transaction_a)); @@ -792,6 +804,21 @@ nano::public_key nano::wallet::deterministic_insert (nano::transaction const & t return key; } +nano::public_key nano::wallet::deterministic_insert (uint32_t const index, bool generate_work_a) +{ + auto transaction (wallets.tx_begin_write ()); + nano::public_key key (0); + if (store.valid_password (transaction)) + { + key = store.deterministic_insert (transaction, index); + if (generate_work_a) + { + work_ensure (key, key); + } + } + return key; +} + nano::public_key nano::wallet::deterministic_insert (bool generate_work_a) { auto transaction (wallets.tx_begin_write ()); diff --git a/nano/node/wallet.hpp b/nano/node/wallet.hpp index 6debd9385..26cd6f229 100644 --- a/nano/node/wallet.hpp +++ b/nano/node/wallet.hpp @@ -57,6 +57,7 @@ public: void seed_set (nano::transaction const &, nano::raw_key const &); nano::key_type key_type (nano::wallet_value const &); nano::public_key deterministic_insert (nano::transaction const &); + nano::public_key deterministic_insert (nano::transaction const &, uint32_t const); void deterministic_key (nano::raw_key &, nano::transaction const &, uint32_t); uint32_t deterministic_index_get (nano::transaction const &); void deterministic_index_set (nano::transaction const &, uint32_t); @@ -132,6 +133,7 @@ public: nano::public_key insert_adhoc (nano::transaction const &, nano::raw_key const &, bool = true); void insert_watch (nano::transaction const &, nano::public_key const &); nano::public_key deterministic_insert (nano::transaction const &, bool = true); + nano::public_key deterministic_insert (uint32_t, bool = true); nano::public_key deterministic_insert (bool = true); bool exists (nano::public_key const &); bool import (std::string const &, std::string const &);