Fix possible wallet locked errors in RPC (#977)

send, receive, change
This commit is contained in:
SergiySW 2018-07-20 10:44:44 +03:00 committed by GitHub
commit cac2e8e751
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 193 additions and 164 deletions

View file

@ -596,65 +596,80 @@ void rai::rpc_handler::account_representative_set ()
if (existing != node.wallets.items.end ())
{
auto wallet (existing->second);
std::string account_text (request.get<std::string> ("account"));
rai::account account;
auto error (account.decode_account (account_text));
if (!error)
if (wallet->valid_password ())
{
std::string representative_text (request.get<std::string> ("representative"));
rai::account representative;
auto error (representative.decode_account (representative_text));
std::string account_text (request.get<std::string> ("account"));
rai::account account;
auto error (account.decode_account (account_text));
if (!error)
{
uint64_t work (0);
boost::optional<std::string> work_text (request.get_optional<std::string> ("work"));
if (work_text.is_initialized ())
std::string representative_text (request.get<std::string> ("representative"));
rai::account representative;
auto error (representative.decode_account (representative_text));
if (!error)
{
auto work_error (rai::from_string_hex (work_text.get (), work));
if (work_error)
uint64_t work (0);
boost::optional<std::string> work_text (request.get_optional<std::string> ("work"));
if (work_text.is_initialized ())
{
error_response (response, "Bad work");
}
}
if (work)
{
rai::transaction transaction (node.store.environment, nullptr, true);
rai::account_info info;
if (!node.store.account_get (transaction, account, info))
{
if (!rai::work_validate (info.head, work))
auto work_error (rai::from_string_hex (work_text.get (), work));
if (work_error)
{
existing->second->store.work_put (transaction, account, work);
error_response (response, "Bad work");
}
}
if (work)
{
rai::transaction transaction (node.store.environment, nullptr, true);
rai::account_info info;
if (!node.store.account_get (transaction, account, info))
{
if (!rai::work_validate (info.head, work))
{
existing->second->store.work_put (transaction, account, work);
}
else
{
error_response (response, "Invalid work");
}
}
else
{
error_response (response, "Invalid work");
error_response (response, "Account not found");
}
}
else
{
error_response (response, "Account not found");
}
auto response_a (response);
wallet->change_async (account, representative, [response_a](std::shared_ptr<rai::block> block) {
rai::block_hash hash (0);
if (block != nullptr)
{
hash = block->hash ();
}
boost::property_tree::ptree response_l;
response_l.put ("block", hash.to_string ());
response_a (response_l);
},
work == 0);
}
auto response_a (response);
wallet->change_async (account, representative, [response_a](std::shared_ptr<rai::block> block) {
rai::block_hash hash (0);
if (block != nullptr)
{
hash = block->hash ();
}
boost::property_tree::ptree response_l;
response_l.put ("block", hash.to_string ());
response_a (response_l);
},
work == 0);
}
else
{
error_response (response, "Bad account number");
}
}
else
{
error_response (response, "Bad account number");
error_response (response, "Wallet locked");
}
}
else
{
error_response (response, "Wallet not found");
}
}
else
{
error_response (response, "Bad wallet number");
}
}
else
@ -2756,98 +2771,105 @@ void rai::rpc_handler::receive ()
auto existing (node.wallets.items.find (wallet));
if (existing != node.wallets.items.end ())
{
std::string account_text (request.get<std::string> ("account"));
rai::account account;
auto error (account.decode_account (account_text));
if (!error)
if (existing->second->valid_password ())
{
rai::transaction transaction (node.store.environment, nullptr, false);
auto account_check (existing->second->store.find (transaction, account));
if (account_check != existing->second->store.end ())
std::string account_text (request.get<std::string> ("account"));
rai::account account;
auto error (account.decode_account (account_text));
if (!error)
{
std::string hash_text (request.get<std::string> ("block"));
rai::uint256_union hash;
auto error (hash.decode_hex (hash_text));
if (!error)
rai::transaction transaction (node.store.environment, nullptr, false);
auto account_check (existing->second->store.find (transaction, account));
if (account_check != existing->second->store.end ())
{
auto block (node.store.block_get (transaction, hash));
if (block != nullptr)
std::string hash_text (request.get<std::string> ("block"));
rai::uint256_union hash;
auto error (hash.decode_hex (hash_text));
if (!error)
{
if (node.store.pending_exists (transaction, rai::pending_key (account, hash)))
auto block (node.store.block_get (transaction, hash));
if (block != nullptr)
{
uint64_t work (0);
boost::optional<std::string> work_text (request.get_optional<std::string> ("work"));
auto error (false);
if (work_text.is_initialized ())
if (node.store.pending_exists (transaction, rai::pending_key (account, hash)))
{
error = rai::from_string_hex (work_text.get (), work);
if (error)
uint64_t work (0);
boost::optional<std::string> work_text (request.get_optional<std::string> ("work"));
auto error (false);
if (work_text.is_initialized ())
{
error_response (response, "Bad work");
}
}
if (work)
{
rai::account_info info;
rai::uint256_union head;
if (!node.store.account_get (transaction, account, info))
{
head = info.head;
}
else
{
head = account;
}
if (!rai::work_validate (head, work))
{
rai::transaction transaction_a (node.store.environment, nullptr, true);
existing->second->store.work_put (transaction_a, account, work);
}
else
{
error = true;
error_response (response, "Invalid work");
}
}
if (!error)
{
auto response_a (response);
existing->second->receive_async (std::move (block), account, rai::genesis_amount, [response_a](std::shared_ptr<rai::block> block_a) {
rai::uint256_union hash_a (0);
if (block_a != nullptr)
error = rai::from_string_hex (work_text.get (), work);
if (error)
{
hash_a = block_a->hash ();
error_response (response, "Bad work");
}
boost::property_tree::ptree response_l;
response_l.put ("block", hash_a.to_string ());
response_a (response_l);
},
work == 0);
}
if (work)
{
rai::account_info info;
rai::uint256_union head;
if (!node.store.account_get (transaction, account, info))
{
head = info.head;
}
else
{
head = account;
}
if (!rai::work_validate (head, work))
{
rai::transaction transaction_a (node.store.environment, nullptr, true);
existing->second->store.work_put (transaction_a, account, work);
}
else
{
error = true;
error_response (response, "Invalid work");
}
}
if (!error)
{
auto response_a (response);
existing->second->receive_async (std::move (block), account, rai::genesis_amount, [response_a](std::shared_ptr<rai::block> block_a) {
rai::uint256_union hash_a (0);
if (block_a != nullptr)
{
hash_a = block_a->hash ();
}
boost::property_tree::ptree response_l;
response_l.put ("block", hash_a.to_string ());
response_a (response_l);
},
work == 0);
}
}
else
{
error_response (response, "Block is not available to receive");
}
}
else
{
error_response (response, "Block is not available to receive");
error_response (response, "Block not found");
}
}
else
{
error_response (response, "Block not found");
error_response (response, "Bad block number");
}
}
else
{
error_response (response, "Bad block number");
error_response (response, "Account not found in wallet");
}
}
else
{
error_response (response, "Account not found in wallet");
error_response (response, "Bad account number");
}
}
else
{
error_response (response, "Bad account number");
error_response (response, "Wallet locked");
}
}
else
@ -3142,99 +3164,106 @@ void rai::rpc_handler::send ()
auto existing (node.wallets.items.find (wallet));
if (existing != node.wallets.items.end ())
{
std::string source_text (request.get<std::string> ("source"));
rai::account source;
auto error (source.decode_account (source_text));
if (!error)
if (existing->second->valid_password ())
{
std::string destination_text (request.get<std::string> ("destination"));
rai::account destination;
auto error (destination.decode_account (destination_text));
std::string source_text (request.get<std::string> ("source"));
rai::account source;
auto error (source.decode_account (source_text));
if (!error)
{
std::string amount_text (request.get<std::string> ("amount"));
rai::amount amount;
auto error (amount.decode_dec (amount_text));
std::string destination_text (request.get<std::string> ("destination"));
rai::account destination;
auto error (destination.decode_account (destination_text));
if (!error)
{
uint64_t work (0);
boost::optional<std::string> work_text (request.get_optional<std::string> ("work"));
if (work_text.is_initialized ())
{
error = rai::from_string_hex (work_text.get (), work);
if (error)
{
error_response (response, "Bad work");
}
}
rai::uint128_t balance (0);
std::string amount_text (request.get<std::string> ("amount"));
rai::amount amount;
auto error (amount.decode_dec (amount_text));
if (!error)
{
rai::transaction transaction (node.store.environment, nullptr, work != 0); // false if no "work" in request, true if work > 0
rai::account_info info;
if (!node.store.account_get (transaction, source, info))
uint64_t work (0);
boost::optional<std::string> work_text (request.get_optional<std::string> ("work"));
if (work_text.is_initialized ())
{
balance = (info.balance).number ();
}
else
{
error = true;
error_response (response, "Account not found");
}
if (!error && work)
{
if (!rai::work_validate (info.head, work))
error = rai::from_string_hex (work_text.get (), work);
if (error)
{
existing->second->store.work_put (transaction, source, work);
error_response (response, "Bad work");
}
}
rai::uint128_t balance (0);
if (!error)
{
rai::transaction transaction (node.store.environment, nullptr, work != 0); // false if no "work" in request, true if work > 0
rai::account_info info;
if (!node.store.account_get (transaction, source, info))
{
balance = (info.balance).number ();
}
else
{
error = true;
error_response (response, "Invalid work");
error_response (response, "Account not found");
}
}
}
if (!error)
{
boost::optional<std::string> send_id (request.get_optional<std::string> ("id"));
if (balance >= amount.number ())
{
auto rpc_l (shared_from_this ());
auto response_a (response);
existing->second->send_async (source, destination, amount.number (), [response_a](std::shared_ptr<rai::block> block_a) {
if (block_a != nullptr)
if (!error && work)
{
if (!rai::work_validate (info.head, work))
{
rai::uint256_union hash (block_a->hash ());
boost::property_tree::ptree response_l;
response_l.put ("block", hash.to_string ());
response_a (response_l);
existing->second->store.work_put (transaction, source, work);
}
else
{
error_response (response_a, "Error generating block");
error = true;
error_response (response, "Invalid work");
}
},
work == 0, send_id);
}
}
else
if (!error)
{
error_response (response, "Insufficient balance");
boost::optional<std::string> send_id (request.get_optional<std::string> ("id"));
if (balance >= amount.number ())
{
auto rpc_l (shared_from_this ());
auto response_a (response);
existing->second->send_async (source, destination, amount.number (), [response_a](std::shared_ptr<rai::block> block_a) {
if (block_a != nullptr)
{
rai::uint256_union hash (block_a->hash ());
boost::property_tree::ptree response_l;
response_l.put ("block", hash.to_string ());
response_a (response_l);
}
else
{
error_response (response_a, "Error generating block");
}
},
work == 0, send_id);
}
else
{
error_response (response, "Insufficient balance");
}
}
}
else
{
error_response (response, "Bad amount format");
}
}
else
{
error_response (response, "Bad amount format");
error_response (response, "Bad destination account");
}
}
else
{
error_response (response, "Bad destination account");
error_response (response, "Bad source account");
}
}
else
{
error_response (response, "Bad source account");
error_response (response, "Wallet locked");
}
}
else

View file

@ -1005,7 +1005,7 @@ std::shared_ptr<rai::block> rai::wallet::send_action (rai::account const & sourc
uint64_t cached_work (0);
store.work_get (transaction, source_a, cached_work);
block.reset (new rai::state_block (source_a, info.head, rep_block->representative (), balance - amount_a, account_a, prv, source_a, cached_work));
if (id_mdb_val)
if (id_mdb_val && block != nullptr)
{
auto status (mdb_put (transaction, node.wallets.send_action_ids, *id_mdb_val, rai::mdb_val (block->hash ()), 0));
if (status != 0)