Repository: Chia-Network/chia-blockchain
File: chia/consensus/block_body_validation.py (Python)

Code before:

        assert len(self.block_hashes) == self.peak_height - self.fork_height
        assert block.height == self.fork_height + 1 + len(self.block_hashes)
        self.block_hashes.append(header_hash)

        self.peak_height = int(block.height)
        self.peak_hash = header_hash

        if conds is not None:
            assert block.foliage_transaction_block is not None
            timestamp = block.foliage_transaction_block.timestamp
            for spend in conds.spends:
                spend_coin_id = bytes32(spend.coin_id)
                spend_ph = bytes32(spend.puzzle_hash)
                self.removals_since_fork[spend_coin_id] = ForkRem(spend_ph, height)
                spend_maybe_ff_singleton = bool(spend.flags & ELIGIBLE_FOR_FF)
                for puzzle_hash, amount, hint in spend.create_coin:
                    child_ph = bytes32(puzzle_hash)
                    child_amount = uint64(amount)
                    child_coin = Coin(spend_coin_id, child_ph, child_amount)
                    child_coin_id = child_coin.name()
                    # See if this child is a potential fast forward singleton too
                    maybe_ff_singleton = (
                        spend_maybe_ff_singleton
                        and child_coin.puzzle_hash == spend.puzzle_hash
                        and amount == spend.coin_amount
                    )
                    self.additions_since_fork[child_coin_id] = ForkAdd(
                        child_coin, height, timestamp, hint, False, maybe_ff_singleton
                    )
        for coin in block.get_included_reward_coins():
            assert block.foliage_transaction_block is not None
            timestamp = block.foliage_transaction_block.timestamp
            assert coin.name() not in self.additions_since_fork
            self.additions_since_fork[coin.name()] = ForkAdd(coin, block.height, timestamp, None, True)

    def rollback(self, header_hash: bytes32, height: int) -> None:
        assert height <= self.peak_height
        self.peak_height = height
        self.peak_hash = header_hash
        self.additions_since_fork = {k: v for k, v in self.additions_since_fork.items() if v.confirmed_height <= height}
        self.removals_since_fork = {k: v for k, v in self.removals_since_fork.items() if v.height <= height}


def validate_block_merkle_roots(
    block_additions_root: bytes32,
    block_removals_root: bytes32,
    tx_additions: list[tuple[Coin, bytes32]],
    tx_removals: list[bytes32],
) -> Optional[Err]:
    # Create addition Merkle set

Review comment (refactor):
any changes to this logic are very hard to spot since you refactored this code at the same time. If you think we should remove this function, doing so (without any logic changes) should be a separate PR.

Code after:
        assert len(self.block_hashes) == self.peak_height - self.fork_height
        assert block.height == self.fork_height + 1 + len(self.block_hashes)
        self.block_hashes.append(header_hash)
        self.peak_height = int(block.height)
        self.peak_hash = header_hash

    def include_reward_coins(self, block: FullBlock) -> None:
        """Updates `self` with `block`'s reward coins."""
        for coin in block.get_included_reward_coins():
            assert block.foliage_transaction_block is not None
            timestamp = block.foliage_transaction_block.timestamp
            coin_id = coin.name()
            assert coin_id not in self.additions_since_fork
            self.additions_since_fork[coin_id] = ForkAdd(
                coin, block.height, timestamp, hint=None, is_coinbase=True, same_as_parent=False
            )

    def include_spends(self, conds: Optional[SpendBundleConditions], block: FullBlock, header_hash: bytes32) -> None:
        self.update_fork_peak(block, header_hash)
        if conds is not None:
            assert block.foliage_transaction_block is not None
            timestamp = block.foliage_transaction_block.timestamp
            for spend in conds.spends:
                spend_coin_id = bytes32(spend.coin_id)
                self.removals_since_fork[spend_coin_id] = ForkRem(bytes32(spend.puzzle_hash), block.height)
                for puzzle_hash, amount, hint in spend.create_coin:
                    coin = Coin(spend_coin_id, bytes32(puzzle_hash), uint64(amount))
                    same_as_parent = coin.puzzle_hash == spend.puzzle_hash and amount == spend.coin_amount
                    self.additions_since_fork[coin.name()] = ForkAdd(
                        coin, block.height, timestamp, hint=hint, is_coinbase=False, same_as_parent=same_as_parent
                    )
        self.include_reward_coins(block)

    def include_block(
        self,
        additions: list[tuple[Coin, Optional[bytes]]],
        removals: list[Coin],
        block: FullBlock,
        header_hash: bytes32,
    ) -> None:
        self.update_fork_peak(block, header_hash)
        if block.foliage_transaction_block is not None:
            timestamp = block.foliage_transaction_block.timestamp
            spent_coins: dict[bytes32, Coin] = {}
            for spend in removals:
                spend_id = bytes32(spend.name())
                spent_coins[spend_id] = spend
                self.removals_since_fork[spend_id] = ForkRem(bytes32(spend.puzzle_hash), block.height)
            for coin, hint in additions:
                parent = spent_coins.get(coin.parent_coin_info)
                assert parent is not None