| 3698 | |
| 3699 | |
| 3700 | static bool ContextualCheckDynaFedHeader(const CBlockHeader& block, BlockValidationState& state, const CChainParams& params, const CBlockIndex* pindexPrev) |
| 3701 | { |
| 3702 | // When not active, it's a NOP |
| 3703 | if (!DeploymentActiveAfter(pindexPrev, params.GetConsensus(), Consensus::DEPLOYMENT_DYNA_FED)) { |
| 3704 | return true; |
| 3705 | } |
| 3706 | |
| 3707 | const DynaFedParams& dynafed_params = block.m_dynafed_params; |
| 3708 | |
| 3709 | // Dynamic blocks must at least publish current signblockscript in full |
| 3710 | if (dynafed_params.m_current.IsNull()) { |
| 3711 | return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "invalid-dyna-fed", "dynamic block headers must have non-empty current signblockscript field"); |
| 3712 | } |
| 3713 | |
| 3714 | // Make sure extension bits aren't active, reserved for future HF |
| 3715 | uint32_t reserved_mask = (1<<23) | (1<<24) | (1<<25) | (1<<26); |
| 3716 | if ((block.nVersion & reserved_mask) != 0) { |
| 3717 | return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "invalid-dyna-fed", "dynamic block header has unknown HF extension bits set"); |
| 3718 | } |
| 3719 | |
| 3720 | const DynaFedParamEntry expected_current_params = ComputeNextBlockCurrentParameters(pindexPrev, params.GetConsensus()); |
| 3721 | |
| 3722 | if (expected_current_params != dynafed_params.m_current) { |
| 3723 | return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "invalid-dyna-fed", "dynamic block header's current parameters do not match expected"); |
| 3724 | } |
| 3725 | |
| 3726 | // Lastly, enforce rules on proposals if they make changes. |
| 3727 | if (!dynafed_params.m_proposed.IsNull()) { |
| 3728 | // Compare the new proposed parameters with the current full parameters. |
| 3729 | const DynaFedParamEntry current = ComputeNextBlockFullCurrentParameters(pindexPrev, params.GetConsensus()); |
| 3730 | const DynaFedParamEntry& proposed = dynafed_params.m_proposed; |
| 3731 | |
| 3732 | if (proposed.m_signblockscript != current.m_signblockscript) { |
| 3733 | // signblockscript proposals *must* be segwit versions |
| 3734 | int block_version = 0; |
| 3735 | std::vector<unsigned char> block_program; |
| 3736 | if (!proposed.m_signblockscript.IsWitnessProgram(block_version, block_program)) { |
| 3737 | return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "invalid-dyna-fed", "proposed signblockscript must be native segwit scriptPubkey"); |
| 3738 | } |
| 3739 | } |
| 3740 | |
| 3741 | if (proposed.m_fedpeg_program != current.m_fedpeg_program || proposed.m_fedpegscript != current.m_fedpegscript) { |
| 3742 | int fedpeg_version = 0; |
| 3743 | std::vector<unsigned char> fedpeg_program; |
| 3744 | if (!proposed.m_fedpeg_program.IsWitnessProgram(fedpeg_version, fedpeg_program)) { |
| 3745 | return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "invalid-dyna-fed", "proposed fedpeg program must be native segwit scriptPubkey"); |
| 3746 | } |
| 3747 | |
| 3748 | // for v0, fedpegscript's scriptPubKey must match. v1+ is unencumbered. |
| 3749 | if (fedpeg_version == 0) { |
| 3750 | uint256 fedpeg_program; |
| 3751 | CSHA256().Write(proposed.m_fedpegscript.data(), proposed.m_fedpegscript.size()).Finalize(fedpeg_program.begin()); |
| 3752 | CScript computed_program = CScript() << OP_0 << ToByteVector(fedpeg_program); |
| 3753 | if (computed_program != proposed.m_fedpeg_program) { |
| 3754 | return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "invalid-dyna-fed", "proposed v0 segwit fedpegscript must match proposed fedpeg witness program"); |
| 3755 | } |
| 3756 | |
| 3757 | // fedpegscript proposals *must not* start with OP_DEPTH |
no test coverage detected