Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Difficulty calculation for RPC block_create #2703

Merged
merged 2 commits into from
Apr 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions nano/node/json_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,41 @@ void nano::json_handler::block_create ()
{
if (work == 0)
{
// Difficulty calculation
if (request.count ("difficulty") == 0)
{
nano::block_details details (nano::epoch::epoch_0, false, false, false);
bool details_found (false);
auto transaction (node.store.tx_begin_read ());
// Previous block find
std::shared_ptr<nano::block> block_previous (nullptr);
if (!previous.is_zero ())
{
block_previous = node.store.block_get (transaction, previous);
}
// Send check
if (block_previous != nullptr)
{
details.is_send = node.store.block_balance (transaction, previous) > balance.number ();
details_found = true;
}
// Epoch check
if (block_previous != nullptr)
{
details.epoch = block_previous->sideband ().details.epoch;
}
if (!link.is_zero () && !details.is_send)
{
auto block_link (node.store.block_get (transaction, link));
if (block_link != nullptr && node.store.pending_exists (transaction, nano::pending_key (pub, link)))
{
details.epoch = std::max (details.epoch, block_link->sideband ().details.epoch);
details.is_receive = true;
details_found = true;
}
}
difficulty_l = details_found ? nano::work_threshold (work_version, details) : node.default_difficulty (work_version);
}
node.work_generate (work_version, root_l, difficulty_l, get_callback_l (block_l), nano::account (pub));
}
else
Expand Down
172 changes: 172 additions & 0 deletions nano/rpc_test/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5999,10 +5999,14 @@ TEST (rpc, block_create_state_open)
ASSERT_NE (nullptr, state_block);
ASSERT_EQ (nano::block_type::state, state_block->type ());
ASSERT_EQ (state_hash, state_block->hash ().to_string ());
auto difficulty (state_block->difficulty ());
ASSERT_GT (difficulty, nano::work_threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_0, false, true, false)));
ASSERT_TRUE (node->latest (key.pub).is_zero ());
scoped_thread_name_io.reset ();
auto process_result (node->process (*state_block));
ASSERT_EQ (nano::process_result::progress, process_result.code);
ASSERT_EQ (state_block->sideband ().details.epoch, nano::epoch::epoch_0);
ASSERT_TRUE (state_block->sideband ().details.is_receive);
ASSERT_FALSE (node->latest (key.pub).is_zero ());
}

Expand Down Expand Up @@ -6054,6 +6058,174 @@ TEST (rpc, block_create_state_request_work)
}
}

TEST (rpc, block_create_open_epoch_v2)
{
nano::system system;
auto node = add_ipc_enabled_node (system);
nano::keypair key;
nano::genesis genesis;
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
ASSERT_NE (nullptr, system.upgrade_genesis_epoch (*node, nano::epoch::epoch_1));
ASSERT_NE (nullptr, system.upgrade_genesis_epoch (*node, nano::epoch::epoch_2));
auto send_block (system.wallet (0)->send_action (nano::test_genesis_key.pub, key.pub, nano::Gxrb_ratio));
ASSERT_NE (nullptr, send_block);
boost::property_tree::ptree request;
request.put ("action", "block_create");
request.put ("type", "state");
request.put ("key", key.prv.data.to_string ());
request.put ("account", key.pub.to_account ());
request.put ("previous", 0);
request.put ("representative", nano::test_genesis_key.pub.to_account ());
request.put ("balance", nano::Gxrb_ratio.convert_to<std::string> ());
request.put ("link", send_block->hash ().to_string ());
scoped_io_thread_name_change scoped_thread_name_io;
nano::node_rpc_config node_rpc_config;
nano::ipc::ipc_server ipc_server (*node, node_rpc_config);
nano::rpc_config rpc_config (nano::get_available_port (), true);
rpc_config.rpc_process.ipc_port = node->config.ipc_config.transport_tcp.port;
nano::ipc_rpc_processor ipc_rpc_processor (system.io_ctx, rpc_config);
nano::rpc rpc (system.io_ctx, rpc_config, ipc_rpc_processor);
rpc.start ();
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_EQ (200, response.status);
std::string state_hash (response.json.get<std::string> ("hash"));
auto state_text (response.json.get<std::string> ("block"));
std::stringstream block_stream (state_text);
boost::property_tree::ptree block_l;
boost::property_tree::read_json (block_stream, block_l);
auto state_block (nano::deserialize_block_json (block_l));
ASSERT_NE (nullptr, state_block);
ASSERT_EQ (nano::block_type::state, state_block->type ());
ASSERT_EQ (state_hash, state_block->hash ().to_string ());
auto difficulty (state_block->difficulty ());
ASSERT_GT (difficulty, nano::work_threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_2, false, true, false)));
ASSERT_TRUE (node->latest (key.pub).is_zero ());
scoped_thread_name_io.reset ();
auto process_result (node->process (*state_block));
ASSERT_EQ (nano::process_result::progress, process_result.code);
ASSERT_EQ (state_block->sideband ().details.epoch, nano::epoch::epoch_2);
ASSERT_TRUE (state_block->sideband ().details.is_receive);
ASSERT_FALSE (node->latest (key.pub).is_zero ());
}

TEST (rpc, block_create_receive_epoch_v2)
{
nano::system system;
auto node = add_ipc_enabled_node (system);
nano::keypair key;
nano::genesis genesis;
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
ASSERT_NE (nullptr, system.upgrade_genesis_epoch (*node, nano::epoch::epoch_1));
auto send_block (system.wallet (0)->send_action (nano::test_genesis_key.pub, key.pub, nano::Gxrb_ratio));
ASSERT_NE (nullptr, send_block);
nano::state_block open (key.pub, 0, nano::test_genesis_key.pub, nano::Gxrb_ratio, send_block->hash (), key.prv, key.pub, *node->work_generate_blocking (key.pub));
ASSERT_EQ (nano::process_result::progress, node->process (open).code);
ASSERT_NE (nullptr, system.upgrade_genesis_epoch (*node, nano::epoch::epoch_2));
auto send_block_2 (system.wallet (0)->send_action (nano::test_genesis_key.pub, key.pub, nano::Gxrb_ratio));
boost::property_tree::ptree request;
request.put ("action", "block_create");
request.put ("type", "state");
request.put ("key", key.prv.data.to_string ());
request.put ("account", key.pub.to_account ());
request.put ("previous", open.hash ().to_string ());
request.put ("representative", nano::test_genesis_key.pub.to_account ());
request.put ("balance", (2 * nano::Gxrb_ratio).convert_to<std::string> ());
request.put ("link", send_block_2->hash ().to_string ());
scoped_io_thread_name_change scoped_thread_name_io;
nano::node_rpc_config node_rpc_config;
nano::ipc::ipc_server ipc_server (*node, node_rpc_config);
nano::rpc_config rpc_config (nano::get_available_port (), true);
rpc_config.rpc_process.ipc_port = node->config.ipc_config.transport_tcp.port;
nano::ipc_rpc_processor ipc_rpc_processor (system.io_ctx, rpc_config);
nano::rpc rpc (system.io_ctx, rpc_config, ipc_rpc_processor);
rpc.start ();
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_EQ (200, response.status);
std::string state_hash (response.json.get<std::string> ("hash"));
auto state_text (response.json.get<std::string> ("block"));
std::stringstream block_stream (state_text);
boost::property_tree::ptree block_l;
boost::property_tree::read_json (block_stream, block_l);
auto state_block (nano::deserialize_block_json (block_l));
ASSERT_NE (nullptr, state_block);
ASSERT_EQ (nano::block_type::state, state_block->type ());
ASSERT_EQ (state_hash, state_block->hash ().to_string ());
auto difficulty (state_block->difficulty ());
ASSERT_GT (difficulty, nano::work_threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_2, false, true, false)));
scoped_thread_name_io.reset ();
auto process_result (node->process (*state_block));
ASSERT_EQ (nano::process_result::progress, process_result.code);
ASSERT_EQ (state_block->sideband ().details.epoch, nano::epoch::epoch_2);
ASSERT_TRUE (state_block->sideband ().details.is_receive);
ASSERT_FALSE (node->latest (key.pub).is_zero ());
}

TEST (rpc, block_create_send_epoch_v2)
{
nano::system system;
auto node = add_ipc_enabled_node (system);
nano::keypair key;
nano::genesis genesis;
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
ASSERT_NE (nullptr, system.upgrade_genesis_epoch (*node, nano::epoch::epoch_1));
ASSERT_NE (nullptr, system.upgrade_genesis_epoch (*node, nano::epoch::epoch_2));
auto send_block (system.wallet (0)->send_action (nano::test_genesis_key.pub, key.pub, nano::Gxrb_ratio));
ASSERT_NE (nullptr, send_block);
nano::state_block open (key.pub, 0, nano::test_genesis_key.pub, nano::Gxrb_ratio, send_block->hash (), key.prv, key.pub, *node->work_generate_blocking (key.pub));
ASSERT_EQ (nano::process_result::progress, node->process (open).code);
boost::property_tree::ptree request;
request.put ("action", "block_create");
request.put ("type", "state");
request.put ("key", key.prv.data.to_string ());
request.put ("account", key.pub.to_account ());
request.put ("previous", open.hash ().to_string ());
request.put ("representative", nano::test_genesis_key.pub.to_account ());
request.put ("balance", 0);
request.put ("link", nano::test_genesis_key.pub.to_string ());
scoped_io_thread_name_change scoped_thread_name_io;
nano::node_rpc_config node_rpc_config;
nano::ipc::ipc_server ipc_server (*node, node_rpc_config);
nano::rpc_config rpc_config (nano::get_available_port (), true);
rpc_config.rpc_process.ipc_port = node->config.ipc_config.transport_tcp.port;
nano::ipc_rpc_processor ipc_rpc_processor (system.io_ctx, rpc_config);
nano::rpc rpc (system.io_ctx, rpc_config, ipc_rpc_processor);
rpc.start ();
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_EQ (200, response.status);
std::string state_hash (response.json.get<std::string> ("hash"));
auto state_text (response.json.get<std::string> ("block"));
std::stringstream block_stream (state_text);
boost::property_tree::ptree block_l;
boost::property_tree::read_json (block_stream, block_l);
auto state_block (nano::deserialize_block_json (block_l));
ASSERT_NE (nullptr, state_block);
ASSERT_EQ (nano::block_type::state, state_block->type ());
ASSERT_EQ (state_hash, state_block->hash ().to_string ());
auto difficulty (state_block->difficulty ());
ASSERT_GT (difficulty, nano::work_threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_2, true, false, false)));
scoped_thread_name_io.reset ();
auto process_result (node->process (*state_block));
ASSERT_EQ (nano::process_result::progress, process_result.code);
ASSERT_EQ (state_block->sideband ().details.epoch, nano::epoch::epoch_2);
ASSERT_TRUE (state_block->sideband ().details.is_send);
ASSERT_FALSE (node->latest (key.pub).is_zero ());
}

TEST (rpc, block_hash)
{
nano::system system;
Expand Down