Skip to content

Commit

Permalink
Block work version (#2599)
Browse files Browse the repository at this point in the history
As of this change, work version refers to different work algorithms. Each block type can unequivocally return its work version. A new algorithm will likely need a new state block definition, to avoid ambiguity, although it could be inferred by trying to validate with both algorithms and then setting the version to the one that was valid (if any).

This change allowed removing work_version as a parameter for some work_validate and work_generate overloads. The work watcher can also infer the version from the block it is watching.
  • Loading branch information
guilhermelawless committed Feb 26, 2020
1 parent 20a13c8 commit 6db4625
Show file tree
Hide file tree
Showing 24 changed files with 96 additions and 109 deletions.
9 changes: 9 additions & 0 deletions nano/core_test/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,15 @@ TEST (state_block, hashing)
ASSERT_EQ (hash, block.hash ());
}

TEST (blocks, work_version)
{
ASSERT_EQ (nano::work_version::work_1, nano::send_block ().work_version ());
ASSERT_EQ (nano::work_version::work_1, nano::receive_block ().work_version ());
ASSERT_EQ (nano::work_version::work_1, nano::change_block ().work_version ());
ASSERT_EQ (nano::work_version::work_1, nano::open_block ().work_version ());
ASSERT_EQ (nano::work_version::work_1, nano::state_block ().work_version ());
}

TEST (block_uniquer, null)
{
nano::block_uniquer uniquer;
Expand Down
10 changes: 5 additions & 5 deletions nano/core_test/distributed_work.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ TEST (distributed_work, no_peers)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_FALSE (nano::work_validate (hash, *work));
ASSERT_FALSE (nano::work_validate (nano::work_version::work_1, hash, *work));
// should only be removed after cleanup
ASSERT_EQ (1, node->distributed_work.items.size ());
while (!node->distributed_work.items.empty ())
Expand Down Expand Up @@ -177,7 +177,7 @@ TEST (distributed_work, peer)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_FALSE (nano::work_validate (hash, *work));
ASSERT_FALSE (nano::work_validate (nano::work_version::work_1, hash, *work));
ASSERT_EQ (1, work_peer->generations_good);
ASSERT_EQ (0, work_peer->generations_bad);
ASSERT_NO_ERROR (system.poll ());
Expand Down Expand Up @@ -207,7 +207,7 @@ TEST (distributed_work, peer_malicious)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_FALSE (nano::work_validate (hash, *work));
ASSERT_FALSE (nano::work_validate (nano::work_version::work_1, hash, *work));
system.deadline_set (5s);
while (malicious_peer->generations_bad < 1)
{
Expand Down Expand Up @@ -265,7 +265,7 @@ TEST (distributed_work, peer_multi)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_FALSE (nano::work_validate (hash, *work));
ASSERT_FALSE (nano::work_validate (nano::work_version::work_1, hash, *work));
system.deadline_set (5s);
while (slow_peer->cancels < 1)
{
Expand Down Expand Up @@ -304,5 +304,5 @@ TEST (distributed_work, fail_resolve)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_FALSE (nano::work_validate (hash, *work));
ASSERT_FALSE (nano::work_validate (nano::work_version::work_1, hash, *work));
}
17 changes: 11 additions & 6 deletions nano/core_test/fakes/work_peer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ class work_peer_connection : public std::enable_shared_from_this<work_peer_conne
const std::string empty_response = "Empty response";

public:
work_peer_connection (asio::io_context & ioc_a, work_peer_type const type_a, nano::work_pool & pool_a, std::function<void(bool const)> on_generation_a, std::function<void()> on_cancel_a) :
work_peer_connection (asio::io_context & ioc_a, work_peer_type const type_a, nano::work_version const version_a, nano::work_pool & pool_a, std::function<void(bool const)> on_generation_a, std::function<void()> on_cancel_a) :
socket (ioc_a),
type (type_a),
version (version_a),
work_pool (pool_a),
on_generation (on_generation_a),
on_cancel (on_cancel_a),
Expand All @@ -53,6 +54,7 @@ class work_peer_connection : public std::enable_shared_from_this<work_peer_conne

private:
work_peer_type type;
nano::work_version version;
nano::work_pool & work_pool;
beast::flat_buffer buffer{ 8192 };
http::request<http::string_body> request;
Expand Down Expand Up @@ -130,10 +132,10 @@ class work_peer_connection : public std::enable_shared_from_this<work_peer_conne
{
auto hash = hash_a;
auto this_l (shared_from_this ());
work_pool.generate (hash, [this_l, hash](boost::optional<uint64_t> work_a) {
work_pool.generate (version, hash, [this_l, hash](boost::optional<uint64_t> work_a) {
auto result = work_a.value_or (0);
uint64_t difficulty;
nano::work_validate (hash, result, &difficulty);
nano::work_validate (this_l->version, hash, result, &difficulty);
static nano::network_params params;
ptree::ptree message_l;
message_l.put ("work", nano::to_string_hex (result));
Expand Down Expand Up @@ -188,12 +190,14 @@ class work_peer_connection : public std::enable_shared_from_this<work_peer_conne
class fake_work_peer : public std::enable_shared_from_this<fake_work_peer>
{
public:
fake_work_peer (nano::work_pool & pool_a, asio::io_context & ioc_a, unsigned short port_a, work_peer_type const type_a) :
fake_work_peer () = delete;
fake_work_peer (nano::work_pool & pool_a, asio::io_context & ioc_a, unsigned short port_a, work_peer_type const type_a, nano::work_version const version_a = nano::work_version::work_1) :
pool (pool_a),
endpoint (tcp::v4 (), port_a),
ioc (ioc_a),
acceptor (ioc_a, endpoint),
type (type_a)
type (type_a),
version (version_a)
{
}
void start ()
Expand All @@ -213,7 +217,7 @@ class fake_work_peer : public std::enable_shared_from_this<fake_work_peer>
{
std::weak_ptr<fake_work_peer> this_w (shared_from_this ());
auto connection (std::make_shared<work_peer_connection> (
ioc, type, pool,
ioc, type, version, pool,
[this_w](bool const good_generation) {
if (auto this_l = this_w.lock ())
{
Expand Down Expand Up @@ -249,5 +253,6 @@ class fake_work_peer : public std::enable_shared_from_this<fake_work_peer>
asio::io_context & ioc;
tcp::acceptor acceptor;
work_peer_type const type;
nano::work_version version;
};
}
10 changes: 5 additions & 5 deletions nano/core_test/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ TEST (wallet, work)
uint64_t work (0);
if (!wallet->store.work_get (transaction, nano::test_genesis_key.pub, work))
{
done = !nano::work_validate (genesis.hash (), work);
done = !nano::work_validate (genesis.open->work_version (), genesis.hash (), work);
}
ASSERT_NO_ERROR (system.poll ());
}
Expand All @@ -669,7 +669,7 @@ TEST (wallet, work_generate)
account1 = system.account (transaction, 0);
}
nano::keypair key;
wallet->send_action (nano::test_genesis_key.pub, key.pub, 100);
auto block (wallet->send_action (nano::test_genesis_key.pub, key.pub, 100));
system.deadline_set (10s);
auto transaction (node1.store.tx_begin_read ());
while (node1.ledger.account_balance (transaction, nano::test_genesis_key.pub) == amount1)
Expand All @@ -683,7 +683,7 @@ TEST (wallet, work_generate)
ASSERT_NO_ERROR (system.poll ());
auto block_transaction (node1.store.tx_begin_read ());
auto transaction (system.wallet (0)->wallets.tx_begin_read ());
again = wallet->store.work_get (transaction, account1, work1) || nano::work_validate (node1.ledger.latest_root (block_transaction, account1), work1);
again = wallet->store.work_get (transaction, account1, work1) || nano::work_validate (block->work_version (), node1.ledger.latest_root (block_transaction, account1), work1);
}
}

Expand Down Expand Up @@ -949,7 +949,7 @@ TEST (wallet, no_work)
auto block (system.wallet (0)->send_action (nano::test_genesis_key.pub, key2.pub, std::numeric_limits<nano::uint128_t>::max (), false));
ASSERT_NE (nullptr, block);
ASSERT_NE (0, block->block_work ());
ASSERT_FALSE (nano::work_validate (block->root (), block->block_work ()));
ASSERT_FALSE (nano::work_validate (*block));
auto transaction (system.wallet (0)->wallets.tx_begin_read ());
uint64_t cached_work (0);
system.wallet (0)->store.work_get (transaction, nano::test_genesis_key.pub, cached_work);
Expand Down Expand Up @@ -1190,7 +1190,7 @@ TEST (wallet, work_watcher_generation_disabled)
auto block (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Mxrb_ratio, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (genesis.hash ())));
uint64_t difficulty (0);
ASSERT_FALSE (nano::work_validate (*block, &difficulty));
node.wallets.watcher->add (block, nano::work_version::work_1);
node.wallets.watcher->add (block);
ASSERT_FALSE (node.process_local (block).code != nano::process_result::progress);
ASSERT_TRUE (node.wallets.watcher->is_watched (block->qualified_root ()));
auto multiplier = nano::difficulty::to_multiplier (difficulty, node.network_params.network.publish_threshold);
Expand Down
16 changes: 8 additions & 8 deletions nano/core_test/work_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ TEST (work, opencl)
for (auto i (0); i < 16; ++i)
{
nano::random_pool::generate_block (root.bytes.data (), root.bytes.size ());
auto result (*pool.generate (root, difficulty));
auto result (*pool.generate (nano::work_version::work_1, root, difficulty));
uint64_t result_difficulty (0);
ASSERT_FALSE (nano::work_validate (root, result, &result_difficulty));
ASSERT_FALSE (nano::work_validate (nano::work_version::work_1, root, result, &result_difficulty));
ASSERT_GE (result_difficulty, difficulty);
difficulty += difficulty_add;
}
Expand Down Expand Up @@ -149,15 +149,15 @@ TEST (work, difficulty)
uint64_t nonce1 (0);
do
{
auto work1 = *pool.generate (root, difficulty1);
nano::work_validate (root, work1, &nonce1);
auto work1 = *pool.generate (nano::work_version::work_1, root, difficulty1);
nano::work_validate (nano::work_version::work_1, root, work1, &nonce1);
} while (nonce1 > difficulty2);
ASSERT_GT (nonce1, difficulty1);
uint64_t nonce2 (0);
do
{
auto work2 = *pool.generate (root, difficulty2);
nano::work_validate (root, work2, &nonce2);
auto work2 = *pool.generate (nano::work_version::work_1, root, difficulty2);
nano::work_validate (nano::work_version::work_1, root, work2, &nonce2);
} while (nonce2 > difficulty3);
ASSERT_GT (nonce2, difficulty2);
}
Expand All @@ -178,8 +178,8 @@ TEST (work, eco_pow)
uint64_t nonce (0);
do
{
auto work = *pool.generate (root, difficulty1);
nano::work_validate (root, work, &nonce);
auto work = *pool.generate (nano::work_version::work_1, root, difficulty1);
nano::work_validate (nano::work_version::work_1, root, work, &nonce);
} while (nonce > difficulty2);
ASSERT_GT (nonce, difficulty1);
}
Expand Down
5 changes: 5 additions & 0 deletions nano/lib/blocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ size_t nano::block::size (nano::block_type type_a)
return result;
}

nano::work_version nano::block::work_version () const
{
return nano::work_version::work_1;
}

nano::block_hash nano::block::generate_hash () const
{
nano::block_hash result;
Expand Down
2 changes: 2 additions & 0 deletions nano/lib/blocks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <nano/lib/numbers.hpp>
#include <nano/lib/stream.hpp>
#include <nano/lib/utility.hpp>
#include <nano/lib/work.hpp>

#include <boost/property_tree/ptree_fwd.hpp>

Expand Down Expand Up @@ -58,6 +59,7 @@ class block
virtual ~block () = default;
virtual bool valid_predecessor (nano::block const &) const = 0;
static size_t size (nano::block_type);
virtual nano::work_version work_version () const;
// If there are any changes to the hashables, call this to update the cached hash
void refresh ();

Expand Down
16 changes: 2 additions & 14 deletions nano/lib/work.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ std::string nano::to_string (nano::work_version const version_a)
return result;
}

bool nano::work_validate (nano::work_version const version_a, nano::block const & block_a, uint64_t * difficulty_a)
bool nano::work_validate (nano::block const & block_a, uint64_t * difficulty_a)
{
return nano::work_validate (version_a, block_a.root (), block_a.block_work (), difficulty_a);
return nano::work_validate (block_a.work_version (), block_a.root (), block_a.block_work (), difficulty_a);
}

bool nano::work_validate (nano::work_version const version_a, nano::root const & root_a, uint64_t const work_a, uint64_t * difficulty_a)
Expand All @@ -40,18 +40,6 @@ bool nano::work_validate (nano::work_version const version_a, nano::root const &
return invalid;
}

bool nano::work_validate (nano::block const & block_a, uint64_t * difficulty_a)
{
return nano::work_validate (block_a.root (), block_a.block_work (), difficulty_a);
}

bool nano::work_validate (nano::root const & root_a, uint64_t const work_a, uint64_t * difficulty_a)
{
static nano::network_constants network_constants;
debug_assert (network_constants.is_test_network ());
return nano::work_validate (nano::work_version::work_1, root_a, work_a, difficulty_a);
}

bool nano::work_v1::validate (nano::root const & root_a, uint64_t work_a, uint64_t * difficulty_a)
{
static nano::network_constants network_constants;
Expand Down
6 changes: 1 addition & 5 deletions nano/lib/work.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,8 @@ enum class work_version
std::string to_string (nano::work_version const version_a);

class block;
bool work_validate (nano::work_version const, nano::block const &, uint64_t * = nullptr);
bool work_validate (nano::work_version const, nano::root const &, uint64_t const, uint64_t * = nullptr);
// For tests only
bool work_validate (nano::block const &, uint64_t * = nullptr);
// For tests only
bool work_validate (nano::root const &, uint64_t const, uint64_t * = nullptr);
bool work_validate (nano::work_version const, nano::root const &, uint64_t const, uint64_t * = nullptr);

namespace work_v1
{
Expand Down
2 changes: 1 addition & 1 deletion nano/nano_node/entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ int main (int argc, char * const * argv)
std::cerr << boost::str (boost::format ("Incorrect sideband block details for block %1%\n") % hash.to_string ());
}
// Check if block work value is correct
if (nano::work_validate (nano::work_version::work_1, *block))
if (nano::work_validate (*block))
{
std::cerr << boost::str (boost::format ("Invalid work for block %1% value: %2%\n") % hash.to_string () % nano::to_string_hex (block->block_work ()));
}
Expand Down
4 changes: 2 additions & 2 deletions nano/node/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ std::pair<std::shared_ptr<nano::election>, bool> nano::active_transactions::inse
auto hash (block_a->hash ());
result.first = nano::make_shared<nano::election> (node, block_a, skip_delay_a, confirmation_action_a);
uint64_t difficulty (0);
release_assert (!nano::work_validate (nano::work_version::work_1, *block_a, &difficulty));
release_assert (!nano::work_validate (*block_a, &difficulty));
roots.get<tag_root> ().emplace (nano::conflict_info{ root, difficulty, difficulty, result.first });
blocks.emplace (hash, result.first);
adjust_difficulty (hash);
Expand Down Expand Up @@ -678,7 +678,7 @@ void nano::active_transactions::update_difficulty (std::shared_ptr<nano::block>
if (existing_election != roots.get<tag_root> ().end ())
{
uint64_t difficulty;
auto error (nano::work_validate (nano::work_version::work_1, *block_a, &difficulty));
auto error (nano::work_validate (*block_a, &difficulty));
(void)error;
debug_assert (!error);
if (difficulty > existing_election->difficulty)
Expand Down
4 changes: 2 additions & 2 deletions nano/node/blockprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void nano::block_processor::add (std::shared_ptr<nano::block> block_a, uint64_t

void nano::block_processor::add (nano::unchecked_info const & info_a)
{
if (!nano::work_validate (nano::work_version::work_1, info_a.block->root (), info_a.block->block_work ()))
if (!nano::work_validate (*info_a.block))
{
{
auto hash (info_a.block->hash ());
Expand Down Expand Up @@ -373,7 +373,7 @@ void nano::block_processor::process_live (nano::block_hash const & hash_a, std::
// Add to work watcher to prevent dropping the election
if (watch_work_a)
{
node.wallets.watcher->add (block_a, nano::work_version::work_1);
node.wallets.watcher->add (block_a);
}

// Start collecting quorum on block
Expand Down
2 changes: 1 addition & 1 deletion nano/node/bootstrap/bootstrap_bulk_pull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ void nano::bulk_pull_client::received_block (boost::system::error_code const & e
{
nano::bufferstream stream (connection->receive_buffer->data (), size_a);
std::shared_ptr<nano::block> block (nano::deserialize_block (stream, type_a));
if (block != nullptr && !nano::work_validate (nano::work_version::work_1, *block))
if (block != nullptr && !nano::work_validate (*block))
{
auto hash (block->hash ());
if (connection->node->config.logging.bulk_pull_logging ())
Expand Down
2 changes: 1 addition & 1 deletion nano/node/bootstrap/bootstrap_bulk_push.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ void nano::bulk_push_server::received_block (boost::system::error_code const & e
{
nano::bufferstream stream (receive_buffer->data (), size_a);
auto block (nano::deserialize_block (stream, type_a));
if (block != nullptr && !nano::work_validate (nano::work_version::work_1, *block))
if (block != nullptr && !nano::work_validate (*block))
{
connection->node->process_active (std::move (block));
throttled_receive ();
Expand Down
6 changes: 3 additions & 3 deletions nano/node/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ void nano::message_parser::deserialize_publish (nano::stream & stream_a, nano::m
nano::publish incoming (error, stream_a, header_a, &block_uniquer);
if (!error && at_end (stream_a))
{
if (!nano::work_validate (nano::work_version::work_1, *incoming.block))
if (!nano::work_validate (*incoming.block))
{
visitor.publish (incoming);
}
Expand All @@ -439,7 +439,7 @@ void nano::message_parser::deserialize_confirm_req (nano::stream & stream_a, nan
nano::confirm_req incoming (error, stream_a, header_a, &block_uniquer);
if (!error && at_end (stream_a))
{
if (incoming.block == nullptr || !nano::work_validate (nano::work_version::work_1, *incoming.block))
if (incoming.block == nullptr || !nano::work_validate (*incoming.block))
{
visitor.confirm_req (incoming);
}
Expand All @@ -465,7 +465,7 @@ void nano::message_parser::deserialize_confirm_ack (nano::stream & stream_a, nan
if (!vote_block.which ())
{
auto block (boost::get<std::shared_ptr<nano::block>> (vote_block));
if (nano::work_validate (nano::work_version::work_1, *block))
if (nano::work_validate (*block))
{
status = parse_status::insufficient_work;
break;
Expand Down
Loading

0 comments on commit 6db4625

Please sign in to comment.