Merge branch 'pulls/156'

This commit is contained in:
clemahieu 2017-07-31 12:31:35 -05:00
commit 558704a5c7
3 changed files with 969 additions and 52 deletions

View file

@ -1238,14 +1238,14 @@ TEST (rpc, peers)
TEST (rpc, pending)
{
rai::system system (24000, 1);
rai::system system (24000, 1);
rai::keypair key1;
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
auto block1 (system.wallet (0)->send_action (rai::test_genesis_key.pub, key1.pub, 100));
rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true));
rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "pending");
boost::property_tree::ptree request;
request.put ("action", "pending");
request.put ("account", key1.pub.to_account ());
request.put ("count", "100");
test_response response (request, rpc, system.service);
@ -1253,11 +1253,39 @@ TEST (rpc, pending)
{
system.poll ();
}
ASSERT_EQ (200, response.status);
auto & blocks_node (response.json.get_child ("blocks"));
ASSERT_EQ (200, response.status);
auto & blocks_node (response.json.get_child ("blocks"));
ASSERT_EQ (1, blocks_node.size ());
rai::block_hash hash1 (blocks_node.begin ()->second.get <std::string> (""));
ASSERT_EQ (block1->hash (), hash1);
request.put ("threshold", "100"); // Threshold test
test_response response0 (request, rpc, system.service);
while (response0.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response0.status);
blocks_node = response0.json.get_child ("blocks");
ASSERT_EQ (1, blocks_node.size ());
std::unordered_map <rai::block_hash, rai::uint128_union> blocks;
for (auto i (blocks_node.begin ()), j (blocks_node.end ()); i != j; ++i)
{
rai::block_hash hash;
hash.decode_hex (i->first);
rai::uint128_union amount;
amount.decode_dec (i->second.get <std::string> (""));
blocks [hash] = amount;
}
ASSERT_EQ (blocks[block1->hash ()], 100);
request.put ("threshold", "101");
test_response response1 (request, rpc, system.service);
while (response1.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response1.status);
blocks_node = response1.json.get_child ("blocks");
ASSERT_EQ (0, blocks_node.size ());
}
TEST (rpc_config, serialization)
@ -1934,23 +1962,26 @@ TEST (rpc, bootstrap_any)
TEST (rpc, republish)
{
rai::system system (24000, 2);
rai::system system (24000, 2);
rai::keypair key;
rai::genesis genesis;
auto latest (system.nodes [0]->latest (rai::test_genesis_key.pub));
auto & node1 (*system.nodes [0]);
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::rpc rpc (system.service, node1, rai::rpc_config (true));
rai::open_block open (send.hash (), 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);
rai::rpc rpc (system.service, node1, rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "republish");
boost::property_tree::ptree request;
request.put ("action", "republish");
request.put ("hash", send.hash ().to_string ());
test_response response (request, rpc, system.service);
while (response.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response.status);
ASSERT_EQ (200, response.status);
auto iterations (0);
while (system.nodes[1]->balance (rai::test_genesis_key.pub) == rai::genesis_amount)
{
@ -1958,6 +1989,50 @@ TEST (rpc, republish)
++iterations;
ASSERT_GT (200, iterations);
}
auto & blocks_node (response.json.get_child ("blocks"));
std::vector <rai::block_hash> blocks;
for (auto i (blocks_node.begin ()), n (blocks_node.end ()); i != n; ++i)
{
blocks.push_back (rai::block_hash (i->second.get <std::string> ("")));
}
ASSERT_EQ (1, blocks.size ());
ASSERT_EQ (send.hash (), blocks [0]);
request.put ("hash", genesis.hash ().to_string ());
request.put ("count", 1);
test_response response1 (request, rpc, system.service);
while (response1.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response1.status);
blocks_node = response1.json.get_child ("blocks");
blocks.clear();
for (auto i (blocks_node.begin ()), n (blocks_node.end ()); i != n; ++i)
{
blocks.push_back (rai::block_hash (i->second.get <std::string> ("")));
}
ASSERT_EQ (1, blocks.size ());
ASSERT_EQ (genesis.hash (), blocks [0]);
request.put ("hash", open.hash ().to_string ());
request.put ("sources", 2);
test_response response2 (request, rpc, system.service);
while (response2.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response2.status);
blocks_node = response2.json.get_child ("blocks");
blocks.clear();
for (auto i (blocks_node.begin ()), n (blocks_node.end ()); i != n; ++i)
{
blocks.push_back (rai::block_hash (i->second.get <std::string> ("")));
}
ASSERT_EQ (3, blocks.size ());
ASSERT_EQ (genesis.hash (), blocks [0]);
ASSERT_EQ (send.hash (), blocks [1]);
ASSERT_EQ (open.hash (), blocks [2]);
}
TEST (rpc, deterministic_key)
@ -2083,6 +2158,28 @@ TEST (rpc, accounts_pending)
rai::block_hash hash1 (blocks.second.begin ()->second.get <std::string> (""));
ASSERT_EQ (block1->hash (), hash1);
}
request.put ("threshold", "100"); // Threshold test
test_response response1 (request, rpc, system.service);
while (response1.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response1.status);
for (auto & pending : response1.json.get_child("blocks"))
{
std::string account_text (pending.first);
ASSERT_EQ (key1.pub.to_account (), account_text);
std::unordered_map <rai::block_hash, rai::uint128_union> blocks;
for (auto i (pending.second.begin ()), j (pending.second.end ()); i != j; ++i)
{
rai::block_hash hash;
hash.decode_hex (i->first);
rai::uint128_union amount;
amount.decode_dec (i->second.get <std::string> (""));
blocks [hash] = amount;
}
ASSERT_EQ (blocks[block1->hash ()], 100);
}
}
TEST (rpc, blocks)
@ -2151,7 +2248,6 @@ TEST (rpc, wallet_balances)
system0.poll ();
}
ASSERT_EQ (200, response.status);
std::vector <std::string> balances;
for (auto & balances : response.json.get_child("balances"))
{
std::string account_text (balances.first);
@ -2162,3 +2258,274 @@ TEST (rpc, wallet_balances)
ASSERT_EQ ("0", pending_text);
}
}
TEST (rpc, pending_exists)
{
rai::system system (24000, 1);
rai::keypair key1;
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
auto hash0 (system.nodes [0]->latest (rai::genesis_account));
auto block1 (system.wallet (0)->send_action (rai::test_genesis_key.pub, key1.pub, 100));
rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "pending_exists");
request.put ("hash", hash0.to_string ());
test_response response0 (request, rpc, system.service);
while (response0.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response0.status);
std::string exists_text (response0.json.get <std::string> ("exists"));
ASSERT_EQ ("0", exists_text);
request.put ("hash", block1->hash ().to_string ());
test_response response1 (request, rpc, system.service);
while (response1.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response1.status);
std::string exists_text1 (response1.json.get <std::string> ("exists"));
ASSERT_EQ ("1", exists_text1);
}
TEST (rpc, wallet_pending)
{
rai::system system0 (24000, 1);
rai::keypair key1;
system0.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
auto block1 (system0.wallet (0)->send_action (rai::test_genesis_key.pub, key1.pub, 100));
rai::rpc rpc (system0.service, *system0.nodes [0], rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "wallet_pending");
request.put ("wallet", system0.nodes [0]->wallets.items.begin ()->first.to_string ());
request.put ("count", "100");
test_response response (request, rpc, system0.service);
while (response.status == 0)
{
system0.poll ();
}
ASSERT_EQ (200, response.status);
for (auto & pending : response.json.get_child("blocks"))
{
std::string account_text (pending.first);
ASSERT_EQ (rai::test_genesis_key.pub.to_account (), account_text);
auto & blocks_node (pending.second.get_child (rai::test_genesis_key.pub.to_account ()));
ASSERT_EQ (1, blocks_node.size ());
rai::block_hash hash1 (blocks_node.begin ()->second.get <std::string> (""));
ASSERT_EQ (block1->hash (), hash1);
}
request.put ("threshold", "100"); // Threshold test
test_response response0 (request, rpc, system0.service);
while (response0.status == 0)
{
system0.poll ();
}
ASSERT_EQ (200, response0.status);
for (auto & pending : response0.json.get_child("blocks"))
{
std::string account_text (pending.first);
ASSERT_EQ (rai::test_genesis_key.pub.to_account (), account_text);
std::unordered_map <rai::block_hash, rai::uint128_union> blocks;
for (auto i (pending.second.begin ()), j (pending.second.end ()); i != j; ++i)
{
rai::block_hash hash;
hash.decode_hex (i->first);
rai::uint128_union amount;
amount.decode_dec (i->second.get <std::string> (""));
blocks [hash] = amount;
}
ASSERT_EQ (blocks[block1->hash ()], 100);
}
request.put ("threshold", "101");
test_response response1 (request, rpc, system0.service);
while (response1.status == 0)
{
system0.poll ();
}
ASSERT_EQ (200, response1.status);
auto & pending1 (response1.json.get_child ("blocks"));
ASSERT_EQ (0, pending1.size ());
}
TEST (rpc, receive_minimum)
{
rai::system system (24000, 1);
rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "receive_minimum");
test_response response (request, rpc, system.service);
while (response.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response.status);
std::string amount (response.json.get <std::string> ("amount"));
ASSERT_EQ (system.nodes [0]->config.receive_minimum.to_string_dec (), amount);
}
TEST (rpc, receive_minimum_set)
{
rai::system system (24000, 1);
rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "receive_minimum_set");
request.put ("amount", "100");
ASSERT_NE (system.nodes [0]->config.receive_minimum.to_string_dec (), "100");
test_response response (request, rpc, system.service);
while (response.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response.status);
std::string success (response.json.get <std::string> ("success"));
ASSERT_TRUE (success.empty());
ASSERT_EQ (system.nodes [0]->config.receive_minimum.to_string_dec (), "100");
}
TEST (rpc, work_get)
{
rai::system system (24000, 1);
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "work_get");
request.put ("wallet", system.nodes [0]->wallets.items.begin ()->first.to_string ());
request.put ("account", rai::test_genesis_key.pub.to_account ());
test_response response (request, rpc, system.service);
while (response.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response.status);
std::string work_text (response.json.get <std::string> ("work"));
uint64_t work (1);
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false);
system.nodes [0]->wallets.items.begin ()->second->store.work_get (transaction, rai::genesis_account, work);
ASSERT_EQ (rai::to_string_hex (work), work_text);
}
TEST (rpc, wallet_work_get)
{
rai::system system (24000, 1);
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "wallet_work_get");
request.put ("wallet", system.nodes [0]->wallets.items.begin ()->first.to_string ());
test_response response (request, rpc, system.service);
while (response.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response.status);
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false);
for (auto & works : response.json.get_child("works"))
{
std::string account_text (works.first);
ASSERT_EQ (rai::test_genesis_key.pub.to_account (), account_text);
std::string work_text (works.second.get <std::string> (""));
uint64_t work (1);
system.nodes [0]->wallets.items.begin ()->second->store.work_get (transaction, rai::genesis_account, work);
ASSERT_EQ (rai::to_string_hex (work), work_text);
}
}
TEST (rpc, work_set)
{
rai::system system (24000, 1);
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
uint64_t work0 (100);
rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "work_set");
request.put ("wallet", system.nodes [0]->wallets.items.begin ()->first.to_string ());
request.put ("account", rai::test_genesis_key.pub.to_account ());
request.put ("work", rai::to_string_hex (work0));
test_response response (request, rpc, system.service);
while (response.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response.status);
std::string success (response.json.get <std::string> ("success"));
ASSERT_TRUE (success.empty());
uint64_t work1 (1);
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, false);
system.nodes [0]->wallets.items.begin ()->second->store.work_get (transaction, rai::genesis_account, work1);
ASSERT_EQ (work1, work0);
}
TEST (rpc, search_pending_all)
{
rai::system system (24000, 1);
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
rai::send_block block (system.nodes [0]->latest (rai::test_genesis_key.pub), rai::test_genesis_key.pub, rai::genesis_amount - system.nodes [0]->config.receive_minimum.number (), rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
ASSERT_EQ (rai::process_result::progress, system.nodes [0]->ledger.process (rai::transaction (system.nodes [0]->store.environment, nullptr, true), block).code);
rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "search_pending_all");
test_response response (request, rpc, system.service);
while (response.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response.status);
auto iterations (0);
while (system.nodes [0]->balance (rai::test_genesis_key.pub) != rai::genesis_amount)
{
system.poll ();
++iterations;
ASSERT_LT (iterations, 200);
}
}
TEST (rpc, wallet_republish)
{
rai::system system (24000, 1);
rai::genesis genesis;
rai::keypair key;
while (key.pub < rai::test_genesis_key.pub)
{
rai::keypair key1;
key.pub = key1.pub;
key.prv.data = key1.prv.data;
}
system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv);
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 (), 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);
rai::rpc rpc (system.service, *system.nodes [0], rai::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "wallet_republish");
request.put ("wallet", system.nodes [0]->wallets.items.begin ()->first.to_string ());
request.put ("count", 1);
test_response response (request, rpc, system.service);
while (response.status == 0)
{
system.poll ();
}
ASSERT_EQ (200, response.status);
auto & blocks_node (response.json.get_child ("blocks"));
std::vector <rai::block_hash> blocks;
for (auto i (blocks_node.begin ()), n (blocks_node.end ()); i != n; ++i)
{
blocks.push_back (rai::block_hash (i->second.get <std::string> ("")));
}
ASSERT_EQ (2, blocks.size ());
ASSERT_EQ (send.hash (), blocks [0]);
ASSERT_EQ (open.hash (), blocks [1]);
}

View file

@ -588,42 +588,72 @@ void rai::rpc_handler::accounts_frontiers ()
void rai::rpc_handler::accounts_pending ()
{
std::string count_text (request.get <std::string> ("count"));
uint64_t count;
if (!decode_unsigned (count_text, count))
uint64_t count (std::numeric_limits <uint64_t>::max ());
rai::uint128_union threshold (0);
try
{
boost::property_tree::ptree response_l;
boost::property_tree::ptree pending;
rai::transaction transaction (node.store.environment, nullptr, false);
for (auto &accounts : request.get_child("accounts"))
std::string count_text (request.get <std::string> ("count"));
auto error (decode_unsigned (count_text, count));
if (error)
{
std::string account_text = accounts.second.data ();
rai::uint256_union account;
if (!account.decode_account (account_text))
error_response (response, "Invalid count");
}
}
catch (std::runtime_error &)
{
// If there is no "count" in request
}
try
{
std::string threshold_text (request.get <std::string> ("threshold"));
auto error_threshold (threshold.decode_dec (threshold_text));
if (error_threshold)
{
error_response (response, "Bad threshold number");
}
}
catch (std::runtime_error &)
{
// If there is no "threshold" in request
}
boost::property_tree::ptree response_l;
boost::property_tree::ptree pending;
rai::transaction transaction (node.store.environment, nullptr, false);
for (auto &accounts : request.get_child("accounts"))
{
std::string account_text = accounts.second.data ();
rai::uint256_union account;
if (!account.decode_account (account_text))
{
boost::property_tree::ptree peers_l;
rai::account end (account.number () + 1);
for (auto i (node.store.pending_begin (transaction, rai::pending_key (account, 0))), n (node.store.pending_begin (transaction, rai::pending_key (end, 0))); i != n && peers_l.size () < count; ++i)
{
boost::property_tree::ptree peers_l;
rai::account end (account.number () + 1);
for (auto i (node.store.pending_begin (transaction, rai::pending_key (account, 0))), n (node.store.pending_begin (transaction, rai::pending_key (end, 0))); i != n && peers_l.size () < count; ++i)
rai::pending_key key (i->first);
if (threshold.is_zero ())
{
rai::pending_key key (i->first);
boost::property_tree::ptree entry;
entry.put ("", key.hash.to_string ());
peers_l.push_back (std::make_pair ("", entry));
}
pending.add_child (account.to_account (), peers_l);
}
else
{
error_response (response, "Bad account number");
else
{
rai::pending_info info (i->second);
if (info.amount.number () >= threshold.number ())
{
peers_l.put (key.hash.to_string (), info.amount.number ().convert_to <std::string> ());
}
}
}
pending.add_child (account.to_account (), peers_l);
}
else
{
error_response (response, "Bad account number");
}
response_l.add_child ("blocks", pending);
response (response_l);
}
else
{
error_response (response, "Invalid count");
}
response_l.add_child ("blocks", pending);
response (response_l);
}
void rai::rpc_handler::available_supply ()
@ -1317,26 +1347,60 @@ void rai::rpc_handler::pending ()
rai::account account;
if (!account.decode_account(account_text))
{
std::string count_text (request.get <std::string> ("count"));
uint64_t count;
if (!decode_unsigned (count_text, count))
uint64_t count (std::numeric_limits <uint64_t>::max ());
rai::uint128_union threshold (0);
try
{
boost::property_tree::ptree response_l;
boost::property_tree::ptree peers_l;
std::string count_text (request.get <std::string> ("count"));
auto error (decode_unsigned (count_text, count));
if (error)
{
rai::transaction transaction (node.store.environment, nullptr, false);
rai::account end (account.number () + 1);
for (auto i (node.store.pending_begin (transaction, rai::pending_key (account, 0))), n (node.store.pending_begin (transaction, rai::pending_key (end, 0))); i != n && peers_l.size ()< count; ++i)
error_response (response, "Invalid count");
}
}
catch (std::runtime_error &)
{
// If there is no "count" in request
}
try
{
std::string threshold_text (request.get <std::string> ("threshold"));
auto error_threshold (threshold.decode_dec (threshold_text));
if (error_threshold)
{
error_response (response, "Bad threshold number");
}
}
catch (std::runtime_error &)
{
// If there is no "threshold" in request
}
boost::property_tree::ptree response_l;
boost::property_tree::ptree peers_l;
{
rai::transaction transaction (node.store.environment, nullptr, false);
rai::account end (account.number () + 1);
for (auto i (node.store.pending_begin (transaction, rai::pending_key (account, 0))), n (node.store.pending_begin (transaction, rai::pending_key (end, 0))); i != n && peers_l.size ()< count; ++i)
{
rai::pending_key key (i->first);
if (threshold.is_zero ())
{
rai::pending_key key (i->first);
boost::property_tree::ptree entry;
entry.put ("", key.hash.to_string ());
peers_l.push_back (std::make_pair ("", entry));
}
else
{
rai::pending_info info (i->second);
if (info.amount.number () >= threshold.number ())
{
peers_l.put (key.hash.to_string (), info.amount.number ().convert_to <std::string> ());
}
}
}
response_l.add_child ("blocks", peers_l);
response (response_l);
}
response_l.add_child ("blocks", peers_l);
response (response_l);
}
else
{
@ -1344,6 +1408,35 @@ void rai::rpc_handler::pending ()
}
}
void rai::rpc_handler::pending_exists ()
{
std::string hash_text (request.get <std::string> ("hash"));
rai::uint256_union hash;
auto error (hash.decode_hex (hash_text));
if (!error)
{
rai::transaction transaction (node.store.environment, nullptr, false);
auto block (node.store.block_get (transaction, hash));
if (block != nullptr)
{
auto block_l (static_cast <rai::send_block *> (block.release ()));
auto account (block_l->hashables.destination);
boost::property_tree::ptree response_l;
auto exists (node.store.pending_exists (transaction, rai::pending_key (account, hash)));
response_l.put ("exists", exists ? "1" : "0");
response (response_l);
}
else
{
error_response (response, "Block not found");
}
}
else
{
error_response (response, "Bad hash number");
}
}
void rai::rpc_handler::payment_begin ()
{
std::string id_text (request.get <std::string> ("wallet"));
@ -1691,6 +1784,44 @@ void rai::rpc_handler::receive ()
}
}
void rai::rpc_handler::receive_minimum ()
{
if (rpc.config.enable_control)
{
boost::property_tree::ptree response_l;
response_l.put ("amount", node.config.receive_minimum.to_string_dec ());
response (response_l);
}
else
{
error_response (response, "RPC control is disabled");
}
}
void rai::rpc_handler::receive_minimum_set ()
{
if (rpc.config.enable_control)
{
std::string amount_text (request.get <std::string> ("amount"));
rai::uint128_union amount;
if (!amount.decode_dec (amount_text))
{
node.config.receive_minimum = amount;
boost::property_tree::ptree response_l;
response_l.put ("success", "");
response (response_l);
}
else
{
error_response (response, "Bad amount number");
}
}
else
{
error_response (response, "RPC control is disabled");
}
}
void rai::rpc_handler::representatives ()
{
boost::property_tree::ptree response_l;
@ -1708,23 +1839,77 @@ void rai::rpc_handler::representatives ()
void rai::rpc_handler::republish ()
{
uint64_t count (2048U);
uint64_t sources (0);
try
{
std::string count_text (request.get <std::string> ("count"));
auto error (decode_unsigned (count_text, count));
if (error)
{
error_response (response, "Invalid count");
}
}
catch (std::runtime_error &)
{
// If there is no "count" in request
}
try
{
std::string sources_text (request.get <std::string> ("sources"));
auto error (decode_unsigned (sources_text, sources));
if (error)
{
error_response (response, "Invalid sources number");
}
}
catch (std::runtime_error &)
{
// If there is no "sources" in request
}
std::string hash_text (request.get <std::string> ("hash"));
rai::uint256_union hash;
auto error (hash.decode_hex (hash_text));
if (!error)
{
boost::property_tree::ptree response_l;
boost::property_tree::ptree blocks;
rai::transaction transaction (node.store.environment, nullptr, false);
auto block (node.store.block_get (transaction, hash));
if (block != nullptr)
{
while (!hash.is_zero ())
for (auto i (0); !hash.is_zero () && i < count; ++i)
{
block = node.store.block_get (transaction, hash);
node.network.republish_block (std::move (block));
if (sources != 0) // Republish source chain
{
std::unique_ptr <rai::block> block_a;
rai::block_hash source (block->source ());
std::vector <rai::block_hash> hashes;
while (!source.is_zero () && hashes.size () < sources)
{
hashes.push_back (source);
block_a = node.store.block_get (transaction, source);
source = block_a->previous ();
}
std::reverse (hashes.begin (), hashes.end ());
for (auto & hash_l : hashes)
{
block_a = node.store.block_get (transaction, hash_l);
node.network.republish_block (std::move (block_a));
boost::property_tree::ptree entry_l;
entry_l.put ("", hash_l.to_string ());
blocks.push_back (std::make_pair ("", entry_l));
}
}
node.network.republish_block (std::move (block)); // Republish block
boost::property_tree::ptree entry;
entry.put ("", hash.to_string ());
blocks.push_back (std::make_pair ("", entry));
hash = node.store.block_successor (transaction, hash);
}
boost::property_tree::ptree response_l;
response_l.put ("success", "");
response_l.put ("success", ""); // obsolete
response_l.add_child ("blocks", blocks);
response (response_l);
}
else
@ -1767,6 +1952,21 @@ void rai::rpc_handler::search_pending ()
}
}
void rai::rpc_handler::search_pending_all ()
{
if (rpc.config.enable_control)
{
node.wallets.search_pending_all ();
boost::property_tree::ptree response_l;
response_l.put ("success", "");
response (response_l);
}
else
{
error_response (response, "RPC control is disabled");
}
}
void rai::rpc_handler::send ()
{
if (rpc.config.enable_control)
@ -2220,6 +2420,89 @@ void rai::rpc_handler::wallet_key_valid ()
}
}
void rai::rpc_handler::wallet_pending ()
{
std::string wallet_text (request.get <std::string> ("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 ())
{
uint64_t count (std::numeric_limits <uint64_t>::max ());
rai::uint128_union threshold (0);
try
{
std::string count_text (request.get <std::string> ("count"));
auto error_count (decode_unsigned (count_text, count));
if (error_count)
{
error_response (response, "Invalid count");
}
}
catch (std::runtime_error &)
{
// If there is no "count" in request
}
try
{
std::string threshold_text (request.get <std::string> ("threshold"));
auto error_threshold (threshold.decode_dec (threshold_text));
if (error_threshold)
{
error_response (response, "Bad threshold number");
}
}
catch (std::runtime_error &)
{
// If there is no "threshold" in request
}
boost::property_tree::ptree response_l;
boost::property_tree::ptree pending;
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);
boost::property_tree::ptree peers_l;
rai::account end (account.number () + 1);
for (auto ii (node.store.pending_begin (transaction, rai::pending_key (account, 0))), nn (node.store.pending_begin (transaction, rai::pending_key (end, 0))); ii != nn && peers_l.size ()< count; ++ii)
{
rai::pending_key key (ii->first);
if (threshold.is_zero ())
{
boost::property_tree::ptree entry;
entry.put ("", key.hash.to_string ());
peers_l.push_back (std::make_pair ("", entry));
}
else
{
rai::pending_info info (ii->second);
if (info.amount.number () >= threshold.number ())
{
peers_l.put (key.hash.to_string (), info.amount.number ().convert_to <std::string> ());
}
}
}
if (!peers_l.empty ())
{
pending.add_child (account.to_account (), peers_l);
}
}
response_l.add_child ("blocks", pending);
response (response_l);
}
else
{
error_response (response, "Wallet not found");
}
}
else
{
error_response (response, "Bad wallet number");
}
}
void rai::rpc_handler::wallet_representative ()
{
std::string wallet_text (request.get <std::string> ("wallet"));
@ -2290,6 +2573,113 @@ void rai::rpc_handler::wallet_representative_set ()
}
}
void rai::rpc_handler::wallet_republish ()
{
if (rpc.config.enable_control)
{
std::string wallet_text (request.get <std::string> ("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 ())
{
uint64_t count;
std::string count_text (request.get <std::string> ("count"));
auto error (decode_unsigned (count_text, count));
if (!error)
{
boost::property_tree::ptree response_l;
boost::property_tree::ptree blocks;
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);
auto latest (node.ledger.latest (transaction, account));
std::unique_ptr <rai::block> block;
std::vector <rai::block_hash> hashes;
while (!latest.is_zero () && hashes.size () < count)
{
hashes.push_back (latest);
block = node.store.block_get (transaction, latest);
latest = block->previous ();
}
std::reverse (hashes.begin (), hashes.end ());
for (auto & hash : hashes)
{
block = node.store.block_get (transaction, hash);
node.network.republish_block (std::move (block));;
boost::property_tree::ptree entry;
entry.put ("", hash.to_string ());
blocks.push_back (std::make_pair ("", entry));
}
}
response_l.add_child ("blocks", blocks);
response (response_l);
}
else
{
error_response (response, "Invalid count");
}
}
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_work_get ()
{
if (rpc.config.enable_control)
{
std::string wallet_text (request.get <std::string> ("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 works;
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);
uint64_t work (0);
auto error_work (existing->second->store.work_get (transaction, account, work));
works.put (account.to_account (), rai::to_string_hex (work));
}
response_l.add_child ("works", works);
response (response_l);
}
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::work_generate ()
{
if (rpc.config.enable_control)
@ -2349,6 +2739,121 @@ void rai::rpc_handler::work_cancel ()
}
}
void rai::rpc_handler::work_get ()
{
if (rpc.config.enable_control)
{
std::string wallet_text (request.get <std::string> ("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 ())
{
std::string account_text (request.get <std::string> ("account"));
rai::account account;
auto error (account.decode_account (account_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 ())
{
uint64_t work (0);
auto error_work (existing->second->store.work_get (transaction, account, work));
boost::property_tree::ptree response_l;
response_l.put ("work", rai::to_string_hex (work));
response (response_l);
}
else
{
error_response (response, "Account not found in wallet");
}
}
else
{
error_response (response, "Bad account number");
}
}
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::work_set ()
{
if (rpc.config.enable_control)
{
std::string wallet_text (request.get <std::string> ("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 ())
{
std::string account_text (request.get <std::string> ("account"));
rai::account account;
auto error (account.decode_account (account_text));
if (!error)
{
rai::transaction transaction (node.store.environment, nullptr, true);
auto account_check (existing->second->store.find (transaction, account));
if (account_check != existing->second->store.end ())
{
std::string work_text (request.get <std::string> ("work"));
uint64_t work;
auto work_error (rai::from_string_hex (work_text, work));
if (!work_error)
{
existing->second->store.work_put (transaction, account, work);
boost::property_tree::ptree response_l;
response_l.put ("success", "");
response (response_l);
}
else
{
error_response (response, "Bad work");
}
}
else
{
error_response (response, "Account not found in wallet");
}
}
else
{
error_response (response, "Bad account number");
}
}
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::work_validate ()
{
std::string hash_text (request.get <std::string> ("hash"));
@ -2638,6 +3143,10 @@ void rai::rpc_handler::process_request ()
{
pending ();
}
else if (action == "pending_exists")
{
pending_exists ();
}
else if (action == "process")
{
process ();
@ -2654,6 +3163,14 @@ void rai::rpc_handler::process_request ()
{
receive ();
}
else if (action == "receive_minimum")
{
receive_minimum ();
}
else if (action == "receive_minimum_set")
{
receive_minimum_set ();
}
else if (action == "representatives")
{
representatives ();
@ -2666,6 +3183,10 @@ void rai::rpc_handler::process_request ()
{
search_pending ();
}
else if (action == "search_pending_all")
{
search_pending_all ();
}
else if (action == "send")
{
send ();
@ -2722,6 +3243,10 @@ void rai::rpc_handler::process_request ()
{
wallet_key_valid ();
}
else if (action == "wallet_pending")
{
wallet_pending ();
}
else if (action == "wallet_representative")
{
wallet_representative ();
@ -2730,6 +3255,14 @@ void rai::rpc_handler::process_request ()
{
wallet_representative_set ();
}
else if (action == "wallet_republish")
{
wallet_republish ();
}
else if (action == "wallet_work_get")
{
wallet_work_get ();
}
else if (action == "work_generate")
{
work_generate ();
@ -2738,6 +3271,14 @@ void rai::rpc_handler::process_request ()
{
work_cancel ();
}
else if (action == "work_get")
{
work_get ();
}
else if (action == "work_set")
{
work_set ();
}
else if (action == "work_validate")
{
work_validate ();

View file

@ -132,13 +132,17 @@ public:
void payment_wait ();
void peers ();
void pending ();
void pending_exists ();
void process ();
void rai_to_raw ();
void rai_from_raw ();
void receive ();
void receive_minimum ();
void receive_minimum_set ();
void representatives ();
void republish ();
void search_pending ();
void search_pending_all ();
void send ();
void stop ();
void successors ();
@ -154,10 +158,15 @@ public:
void wallet_export ();
void wallet_frontiers ();
void wallet_key_valid ();
void wallet_pending ();
void wallet_representative ();
void wallet_representative_set ();
void wallet_republish ();
void wallet_work_get ();
void work_generate ();
void work_cancel ();
void work_get ();
void work_set ();
void work_validate ();
std::string body;
rai::node & node;