@@ -592,6 +592,30 @@ size_t block::segregated() const NOEXCEPT
592592 return std::count_if (txs_->begin (), txs_->end (), count_segregated);
593593}
594594
595+ // Last output of commitment pattern holds the committed value (bip141).
596+ bool block::get_witness_commitment (hash_cref& commitment) const NOEXCEPT
597+ {
598+ if (txs_->empty ())
599+ return false ;
600+
601+ const auto & outputs = *txs_->front ()->outputs_ptr ();
602+ for (const auto & output: std::views::reverse (outputs))
603+ if (output->committed_hash (commitment))
604+ return true ;
605+
606+ return false ;
607+ }
608+
609+ // Coinbase input witness must be 32 byte witness reserved value (bip141).
610+ bool block::get_witness_reservation (hash_cref& reservation) const NOEXCEPT
611+ {
612+ if (txs_->empty ())
613+ return false ;
614+
615+ const auto & inputs = *txs_->front ()->inputs_ptr ();
616+ return !inputs.empty () && inputs.front ()->reserved_hash (reservation);
617+ }
618+
595619// The witness merkle root is obtained from wtxids, subject to malleation just
596620// as the txs commitment. However, since tx duplicates are precluded by the
597621// malleable32 (or complete) block check, there is no opportunity for this.
@@ -601,26 +625,19 @@ bool block::is_invalid_witness_commitment() const NOEXCEPT
601625 if (txs_->empty ())
602626 return false ;
603627
604- const auto & coinbase = txs_->front ();
605- if (coinbase->inputs_ptr ()->empty ())
606- return false ;
607-
628+ // Witness data (segregated) disallowed if no commitment (bip141).
608629 // If no block tx has witness data the commitment is optional (bip141).
609- if (!is_segregated ())
610- return false ;
630+ hash_cref commit{ null_hash };
631+ if (!get_witness_commitment (commit))
632+ return is_segregated ();
611633
612- // If there is a valid commitment, return false (valid).
613- // Coinbase input witness must be 32 byte witness reserved value (bip141).
614- // Last output of commitment pattern holds the committed value (bip141).
615- hash_digest reserved{}, committed{};
616- if (coinbase->inputs_ptr ()->front ()->reserved_hash (reserved))
617- for (const auto & output: std::views::reverse (*coinbase->outputs_ptr ()))
618- if (output->committed_hash (committed))
619- if (committed == sha256::double_hash (
620- generate_merkle_root (true ), reserved))
621- return false ;
634+ // If there is a witness reservation there must be a commitment (bip141).
635+ hash_cref reserve{ null_hash };
636+ if (!get_witness_reservation (reserve))
637+ return true ;
622638
623- return true ;
639+ // If there is a valid commitment, return false (valid).
640+ return commit != sha256::double_hash (generate_merkle_root (true ), reserve);
624641}
625642
626643// *****************************************************************************
@@ -851,6 +868,7 @@ code block::identify() const NOEXCEPT
851868 return error::block_success;
852869}
853870
871+ // bip141 should be disabled when the node is not accepting witness data.
854872code block::identify (const context& ctx) const NOEXCEPT
855873{
856874 const auto bip141 = ctx.is_enabled (bip141_rule);
@@ -894,6 +912,7 @@ code block::check() const NOEXCEPT
894912// median_time_past
895913
896914// TODO: use of get_hash() in is_hash_limit_exceeded makes this thread unsafe.
915+ // bip141 should be disabled when the node is not accepting witness data.
897916code block::check (const context& ctx) const NOEXCEPT
898917{
899918 const auto bip141 = ctx.is_enabled (bip141_rule);
0 commit comments