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

Code before:
                transaction, cost_result, spend_name, self.mempool_manager.peak.height
            )
            status = info.status
            error = info.error
        if status == MempoolInclusionStatus.SUCCESS:
            self.log.debug(
                f"Added transaction to mempool: {spend_name} mempool size: "
                f"{self.mempool_manager.mempool.total_mempool_cost()} normalized "
                f"{self.mempool_manager.mempool.total_mempool_cost() / 5000000}"
            )

            mempool_item = self.mempool_manager.get_mempool_item(spend_name)
            assert mempool_item is not None
            # Now that we validated this transaction, check what fees and
            # costs the peers have advertised for it.
            for peer_id, (advertised_fee, advertised_cost) in peers_with_tx.items():
                if advertised_fee == mempool_item.fee and advertised_cost == mempool_item.cost:
                    continue
                if peer_id not in self.server.all_connections:
                    continue
                self.log.warning(
                    f"Banning peer {peer_id}. Sent us a new tx {spend_name} with mismatch "
                    f"on cost {advertised_cost} vs validation cost {mempool_item.cost} and/or "
                    f"fee {advertised_fee} vs {mempool_item.fee}."
                )
                await self.server.all_connections[peer_id].close(RATE_LIMITER_BAN_SECONDS)
            # Only broadcast successful transactions, not pending ones. Otherwise it's a DOS
            # vector.
            await self.broadcast_removed_tx(info.removals)
            await self.broadcast_added_tx(mempool_item, current_peer=peer)

            if self.simulator_transaction_callback is not None:  # callback
                await self.simulator_transaction_callback(spend_name)

        else:
            self.mempool_manager.remove_seen(spend_name)
            self.log.debug(f"Wasn't able to add transaction with id {spend_name}, status {status} error: {error}")
        return status, error

    async def broadcast_added_tx(
        self, mempool_item: MempoolItem, current_peer: Optional[WSChiaConnection] = None
    ) -> None:
        assert mempool_item.fee >= 0
        assert mempool_item.cost is not None

        new_tx = full_node_protocol.NewTransaction(
            mempool_item.name,
            mempool_item.cost,
            mempool_item.fee,
        )
        msg = make_msg(ProtocolMessageTypes.new_transaction, new_tx)

Review comment (suggestion):
I think `CONSENSUS_ERROR_BAN_SECONDS` is pretty reasonable here. disagreeing on cost or fee is a consensus issue. and I think if you see rate limiter in the log, you won't think of this case

Code after:
                return MempoolInclusionStatus.FAILED, Err.MEMPOOL_NOT_INITIALIZED
            info = await self.mempool_manager.add_spend_bundle(
                transaction, cost_result, spend_name, self.mempool_manager.peak.height
            )
            status = info.status
            error = info.error
        if status == MempoolInclusionStatus.SUCCESS:
            self.log.debug(
                f"Added transaction to mempool: {spend_name} mempool size: "
                f"{self.mempool_manager.mempool.total_mempool_cost()} normalized "
                f"{self.mempool_manager.mempool.total_mempool_cost() / 5000000}"
            )

            mempool_item = self.mempool_manager.get_mempool_item(spend_name)
            assert mempool_item is not None
            # Now that we validated this transaction, check what fees and
            # costs the peers have advertised for it.
            for peer_id, entry in peers_with_tx.items():
                if entry.advertised_fee == mempool_item.fee and entry.advertised_cost == mempool_item.cost:
                    continue
                self.log.warning(
                    f"Banning peer {peer_id}. Sent us a new tx {spend_name} with mismatch "
                    f"on cost {entry.advertised_cost} vs validation cost {mempool_item.cost} and/or "
                    f"fee {entry.advertised_fee} vs {mempool_item.fee}."
                )
                peer = self.server.all_connections.get(peer_id)
                if peer is None:
                    self.server.ban_peer(entry.peer_host, CONSENSUS_ERROR_BAN_SECONDS)
                else:
                    await peer.close(CONSENSUS_ERROR_BAN_SECONDS)
            # Only broadcast successful transactions, not pending ones. Otherwise it's a DOS
            # vector.
            await self.broadcast_removed_tx(info.removals)
            await self.broadcast_added_tx(mempool_item, current_peer=peer)

            if self.simulator_transaction_callback is not None:  # callback
                await self.simulator_transaction_callback(spend_name)

        else:
            self.mempool_manager.remove_seen(spend_name)
            self.log.debug(f"Wasn't able to add transaction with id {spend_name}, status {status} error: {error}")
        return status, error

    async def broadcast_added_tx(
        self, mempool_item: MempoolItem, current_peer: Optional[WSChiaConnection] = None
    ) -> None:
        assert mempool_item.fee >= 0
        assert mempool_item.cost is not None

        new_tx = full_node_protocol.NewTransaction(
            mempool_item.name,