@@ -1529,6 +1529,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
15291529 invalidate_block_template_cache ();
15301530 }
15311531
1532+ const uint64_t cur_n_blocks = m_db->height ();
15321533 if (from_block)
15331534 {
15341535 // build alternative subchain, front -> mainchain, back -> alternative head
@@ -1589,6 +1590,32 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
15891590 b.minor_version = m_hardfork->get_ideal_version ();
15901591 b.prev_id = *from_block;
15911592
1593+ if (b.major_version >= HF_VERSION_FCMP_PLUS_PLUS)
1594+ {
1595+ if (alt_chain.size () > CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE)
1596+ {
1597+ // Since the daemon is not wasting cycles calculating alt-trees, it does
1598+ // not know the correct root to use for an alt chain longer than 10
1599+ // blocks. The daemon could theoretically build the altchain's tree in
1600+ // handle_alternative_block, but that seems like a pre-mature
1601+ // optimization. Who wants to mine altchains longer than 10 blocks
1602+ // anyway?
1603+ MERROR (" altchain is too long, the daemon is not structured to calculate its FCMP++ tree root" );
1604+ return false ;
1605+ }
1606+
1607+ if (height > cur_n_blocks)
1608+ {
1609+ MERROR (" altchain is longer than the mainchain, so we don't have the FCMP++ tree root saved for its block" );
1610+ // Theoretically the daemon could calculate the tree 10 blocks ahead
1611+ // of the mainchain, which would allow us to mine on top of an altchain
1612+ // while growing the mainchain tree (which we need to do anyway), but it
1613+ // seems like pre-mature optimization to support mining on top
1614+ // of altchains longer than the mainchain anyway.
1615+ return false ;
1616+ }
1617+ }
1618+
15921619 // cheat and use the weight of the block we start from, virtually certain to be acceptable
15931620 // and use 1.9 times rather than 2 times so we're even more sure
15941621 if (parent_in_main)
@@ -1611,7 +1638,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
16111638 }
16121639 else
16131640 {
1614- height = m_db-> height () ;
1641+ height = cur_n_blocks ;
16151642 b.major_version = m_hardfork->get_current_version ();
16161643 b.minor_version = m_hardfork->get_ideal_version ();
16171644 b.prev_id = get_tail_id ();
@@ -1635,6 +1662,11 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
16351662
16361663 CHECK_AND_ASSERT_MES (diffic, false , " difficulty overhead." );
16371664
1665+ if (b.major_version >= HF_VERSION_FCMP_PLUS_PLUS)
1666+ {
1667+ m_db->get_tree_root_at_blk_idx (height, b.fcmp_pp_tree_root );
1668+ }
1669+
16381670 size_t txs_weight;
16391671 uint64_t fee;
16401672 if (!m_tx_pool.fill_block_template (b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, b.major_version ))
@@ -1768,15 +1800,21 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
17681800 return create_block_template (b, NULL , miner_address, diffic, height, expected_reward, cumulative_weight, ex_nonce, seed_height, seed_hash);
17691801}
17701802// ------------------------------------------------------------------
1771- bool Blockchain::get_miner_data (uint8_t & major_version, uint64_t & height, crypto::hash& prev_id, crypto::hash& seed_hash, difficulty_type& difficulty, uint64_t & median_weight, uint64_t & already_generated_coins, std::vector<tx_block_template_backlog_entry>& tx_backlog)
1803+ bool Blockchain::get_miner_data (uint8_t & major_version, uint64_t & height, crypto::hash& prev_id, crypto::ec_point& fcmp_pp_tree_root, crypto:: hash& seed_hash, difficulty_type& difficulty, uint64_t & median_weight, uint64_t & already_generated_coins, std::vector<tx_block_template_backlog_entry>& tx_backlog)
17721804{
17731805 prev_id = m_db->top_block_hash (&height);
17741806 ++height;
17751807
17761808 major_version = m_hardfork->get_ideal_version (height);
17771809
1810+ const uint8_t cur_version = m_hardfork->get_current_version ();
1811+
1812+ fcmp_pp_tree_root = crypto::ec_point{};
1813+ if (cur_version >= HF_VERSION_FCMP_PLUS_PLUS)
1814+ m_db->get_tree_root_at_blk_idx (height, fcmp_pp_tree_root);
1815+
17781816 seed_hash = crypto::null_hash;
1779- if (m_hardfork-> get_current_version () >= RX_BLOCK_VERSION)
1817+ if (cur_version >= RX_BLOCK_VERSION)
17801818 {
17811819 uint64_t seed_height, next_height;
17821820 crypto::rx_seedheights (height, &seed_height, &next_height);
@@ -4316,6 +4354,19 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
43164354
43174355 TIME_MEASURE_START (t3);
43184356
4357+ // Make sure the block uses the correct FCMP++ tree root
4358+ if (hf_version >= HF_VERSION_FCMP_PLUS_PLUS)
4359+ {
4360+ crypto::ec_point fcmp_pp_tree_root;
4361+ m_db->get_tree_root_at_blk_idx (blockchain_height, fcmp_pp_tree_root);
4362+ if (bl.fcmp_pp_tree_root != fcmp_pp_tree_root)
4363+ {
4364+ MERROR_VER (" Block with id: " << id << " used incorrect FCMP++ tree root" );
4365+ bvc.m_verifivation_failed = true ;
4366+ goto leave;
4367+ }
4368+ }
4369+
43194370 // sanity check basic miner tx properties;
43204371 if (!prevalidate_miner_transaction (bl, blockchain_height, hf_version))
43214372 {
@@ -4630,14 +4681,36 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
46304681 return false ;
46314682 }
46324683
4684+ // Assume we're adding block n, now we grow the FCMP++ tree and generate a
4685+ // new root that will be usable once block n+1 is in the chain. We keep the
4686+ // tree 1 block ahead of the chain so that miners can use the block's tree
4687+ // root to calculate the next block's PoW hash. Note that we're still growing
4688+ // the tree 1 block at a time in the sync process. We just grow the tree ahead
4689+ // of the "next" block after syncing "this" block. This approach works because
4690+ // outputs are not immediately spendable upon inclusion in the chain. There is
4691+ // room for improvement in parallelizing tree building, left for another day.
4692+ TIME_MEASURE_START (advance_tree);
4693+
4694+ static_assert (CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE > 0 , " Expect a non-0 spendable age" );
4695+ try { m_db->advance_tree_one_block (new_height); }
4696+ catch (const std::exception& e)
4697+ {
4698+ LOG_ERROR (" Failed to advance tree at block with hash: " << id << " , what = " << e.what ());
4699+ bvc.m_verifivation_failed = true ;
4700+ return false ;
4701+ }
4702+
4703+ TIME_MEASURE_FINISH (advance_tree);
4704+
46334705 MINFO (" +++++ BLOCK SUCCESSFULLY ADDED" << std::endl << " id:\t " << id << std::endl << " PoW:\t " << proof_of_work << std::endl << " HEIGHT " << new_height-1 << " , difficulty:\t " << current_diffic << std::endl << " block reward: " << print_money (fee_summary + base_reward) << " (" << print_money (base_reward) << " + " << print_money (fee_summary) << " ), coinbase_weight: " << coinbase_weight << " , cumulative weight: " << cumulative_block_weight << " , " << block_processing_time << " (" << target_calculating_time << " /" << longhash_calculating_time << " )ms" );
46344706 if (m_show_time_stats)
46354707 {
46364708 MINFO (" Height: " << new_height << " coinbase weight: " << coinbase_weight << " cumm: "
46374709 << cumulative_block_weight << " p/t: " << block_processing_time << " ("
46384710 << target_calculating_time << " /" << longhash_calculating_time << " /"
46394711 << t1 << " /" << t2 << " /" << t3 << " /" << t_exists << " /" << t_pool
4640- << " /" << t_checktx << " /" << t_dblspnd << " /" << vmt << " /" << addblock << " )ms" );
4712+ << " /" << t_checktx << " /" << t_dblspnd << " /" << vmt << " /" << addblock
4713+ << " /" << advance_tree << " )ms" );
46414714 }
46424715
46434716 bvc.m_added_to_main_chain = true ;
@@ -5909,9 +5982,13 @@ void Blockchain::send_miner_notifications(uint64_t height, const crypto::hash &s
59095982 std::vector<tx_block_template_backlog_entry> tx_backlog;
59105983 m_tx_pool.get_block_template_backlog (tx_backlog);
59115984
5985+ crypto::ec_point fcmp_pp_tree_root{};
5986+ if (m_hardfork->get_current_version () >= HF_VERSION_FCMP_PLUS_PLUS)
5987+ m_db->get_tree_root_at_blk_idx (height, fcmp_pp_tree_root);
5988+
59125989 for (const auto & notifier : m_miner_notifiers)
59135990 {
5914- notifier (major_version, height, prev_id, seed_hash, diff, median_weight, already_generated_coins, tx_backlog);
5991+ notifier (major_version, height, prev_id, fcmp_pp_tree_root, seed_hash, diff, median_weight, already_generated_coins, tx_backlog);
59155992 }
59165993}
59175994
0 commit comments