diff --git a/nano/core_test/block.cpp b/nano/core_test/block.cpp index e4359503ce..082dab5697 100644 --- a/nano/core_test/block.cpp +++ b/nano/core_test/block.cpp @@ -366,25 +366,36 @@ TEST (state_block, hashing) nano::keypair key; nano::state_block block (key.pub, 0, key.pub, 0, 0, key.prv, key.pub, 0); auto hash (block.hash ()); + ASSERT_EQ (hash, block.hash ()); // check cache works block.hashables.account.bytes[0] ^= 0x1; + block.refresh (); ASSERT_NE (hash, block.hash ()); block.hashables.account.bytes[0] ^= 0x1; + block.refresh (); ASSERT_EQ (hash, block.hash ()); block.hashables.previous.bytes[0] ^= 0x1; + block.refresh (); ASSERT_NE (hash, block.hash ()); block.hashables.previous.bytes[0] ^= 0x1; + block.refresh (); ASSERT_EQ (hash, block.hash ()); block.hashables.representative.bytes[0] ^= 0x1; + block.refresh (); ASSERT_NE (hash, block.hash ()); block.hashables.representative.bytes[0] ^= 0x1; + block.refresh (); ASSERT_EQ (hash, block.hash ()); block.hashables.balance.bytes[0] ^= 0x1; + block.refresh (); ASSERT_NE (hash, block.hash ()); block.hashables.balance.bytes[0] ^= 0x1; + block.refresh (); ASSERT_EQ (hash, block.hash ()); block.hashables.link.bytes[0] ^= 0x1; + block.refresh (); ASSERT_NE (hash, block.hash ()); block.hashables.link.bytes[0] ^= 0x1; + block.refresh (); ASSERT_EQ (hash, block.hash ()); } diff --git a/nano/core_test/bootstrap.cpp b/nano/core_test/bootstrap.cpp index eca7ad2782..d3216b513e 100644 --- a/nano/core_test/bootstrap.cpp +++ b/nano/core_test/bootstrap.cpp @@ -58,6 +58,7 @@ TEST (bulk_pull, end_not_owned) open.hashables.account = key2.pub; open.hashables.representative = key2.pub; open.hashables.source = latest; + open.refresh (); open.signature = nano::sign_message (key2.prv, key2.pub, open.hash ()); system.nodes[0]->work_generate_blocking (open); ASSERT_EQ (nano::process_result::progress, system.nodes[0]->process (open).code); diff --git a/nano/lib/blocks.cpp b/nano/lib/blocks.cpp index fe4ccbf6c4..3c2bb81d6c 100644 --- a/nano/lib/blocks.cpp +++ b/nano/lib/blocks.cpp @@ -76,7 +76,7 @@ size_t nano::block::size (nano::block_type type_a) return result; } -nano::block_hash nano::block::hash () const +nano::block_hash nano::block::generate_hash () const { nano::block_hash result; blake2b_state hash_l; @@ -88,6 +88,30 @@ nano::block_hash nano::block::hash () const return result; } +void nano::block::refresh () +{ + if (!cached_hash.is_zero ()) + { + cached_hash = generate_hash (); + } +} + +nano::block_hash const & nano::block::hash () const +{ + if (!cached_hash.is_zero ()) + { + // Once a block is created, it should not be modified (unless using refresh ()) + // This would invalidate the cache; check it hasn't changed. + assert (cached_hash == generate_hash ()); + } + else + { + cached_hash = generate_hash (); + } + + return cached_hash; +} + nano::block_hash nano::block::full_hash () const { nano::block_hash result; diff --git a/nano/lib/blocks.hpp b/nano/lib/blocks.hpp index 1e3c9a950a..a05aa59406 100644 --- a/nano/lib/blocks.hpp +++ b/nano/lib/blocks.hpp @@ -57,7 +57,7 @@ class block { public: // Return a digest of the hashables in this block. - nano::block_hash hash () const; + nano::block_hash const & hash () const; // Return a digest of hashables and non-hashables in this block. nano::block_hash full_hash () const; std::string to_json () const; @@ -88,6 +88,14 @@ class block virtual ~block () = default; virtual bool valid_predecessor (nano::block const &) const = 0; static size_t size (nano::block_type); + // If there are any changes to the hashables, call this to update the cached hash + void refresh (); + +protected: + mutable nano::block_hash cached_hash{ 0 }; + +private: + nano::block_hash generate_hash () const; }; class send_hashables { diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index 4e8b944a85..6e0ec1cc4f 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -99,7 +99,7 @@ void nano::active_transactions::search_frontiers (nano::transaction const & tran // Calculate votes for local representatives if (representative) { - this->node.block_processor.generator.add (block->hash ()); + this->node.block_processor.generator.add (info.head); } } }