@@ -3959,7 +3959,7 @@ struct controller_impl {
3959
3959
// Called from net-threads. It is thread safe as signed_block is never modified after creation.
3960
3960
// -----------------------------------------------------------------------------
3961
3961
std::optional<qc_t > verify_basic_proper_block_invariants ( const block_id_type& id, const signed_block_ptr& b,
3962
- const block_header_state & prev ) {
3962
+ const block_state & prev ) {
3963
3963
assert (b->is_proper_svnn_block ());
3964
3964
3965
3965
auto qc_ext_id = quorum_certificate_extension::extension_id ();
@@ -4054,6 +4054,20 @@ struct controller_impl {
4054
4054
" QC is_strong (${s1}) in block extension does not match is_strong_qc (${s2}) in header extension. Block number: ${b}" ,
4055
4055
(" s1" , qc_proof.is_strong ())(" s2" , new_qc_claim.is_strong_qc )(" b" , block_num) );
4056
4056
4057
+ // `valid` structure can be modified while this function is running on net thread.
4058
+ // Use is_valid() instead. It uses atomic `validated` and when it is true, `valid`
4059
+ // has been constructed.
4060
+ if (prev.is_valid ()) {
4061
+ assert (prev.valid );
4062
+
4063
+ // compute finality mroot using previous block state and new qc claim
4064
+ auto computed_finality_mroot = prev.get_finality_mroot_claim (new_qc_claim);
4065
+ const auto & supplied_finality_mroot = b->action_mroot ;
4066
+ EOS_ASSERT ( computed_finality_mroot == supplied_finality_mroot, block_validate_exception,
4067
+ " computed finality mroot (${computed}) does not match supplied finality mroot ${supplied} by header extension. Block number: ${b}, block id: ${id}" ,
4068
+ (" computed" , computed_finality_mroot)(" supplied" , supplied_finality_mroot)(" b" , block_num)(" id" , id) );
4069
+ }
4070
+
4057
4071
return std::optional{qc_proof};
4058
4072
}
4059
4073
0 commit comments