@api_request
@peer_required
async def declare_proof_of_space(self, request: farmer_protocol.DeclareProofOfSpace, peer: ws.WSChiaConnection) -> Optional[Message]:
    '\n        Creates a block body and header, with the proof of space, coinbase, and fee targets provided\n        by the farmer, and sends the hash of the header data back to the farmer.\n        '
    if self.full_node.sync_store.get_sync_mode():
        return None
    async with self.full_node.timelord_lock:
        sp_vdfs: Optional[SignagePoint] = self.full_node.full_node_store.get_signage_point(request.challenge_chain_sp)
        if (sp_vdfs is None):
            self.log.warning(f'Received proof of space for an unknown signage point {request.challenge_chain_sp}')
            return None
        if (request.signage_point_index > 0):
            assert (sp_vdfs.rc_vdf is not None)
            if (sp_vdfs.rc_vdf.output.get_hash() != request.reward_chain_sp):
                self.log.debug(f'Received proof of space for a potentially old signage point {request.challenge_chain_sp}. Current sp: {sp_vdfs.rc_vdf.output.get_hash()}')
                return None
        if (request.signage_point_index == 0):
            cc_challenge_hash: bytes32 = request.challenge_chain_sp
        else:
            assert (sp_vdfs.cc_vdf is not None)
            cc_challenge_hash = sp_vdfs.cc_vdf.challenge
        pos_sub_slot: Optional[Tuple[(EndOfSubSlotBundle, int, uint128)]] = None
        if (request.challenge_hash != self.full_node.constants.GENESIS_CHALLENGE):
            pos_sub_slot = self.full_node.full_node_store.get_sub_slot(cc_challenge_hash)
            if (pos_sub_slot is None):
                self.log.warning(f'Received proof of space for an unknown sub slot: {request}')
                return None
            total_iters_pos_slot: uint128 = pos_sub_slot[2]
        else:
            total_iters_pos_slot = uint128(0)
        assert (cc_challenge_hash == request.challenge_hash)
        quality_string: Optional[bytes32] = request.proof_of_space.verify_and_get_quality_string(self.full_node.constants, cc_challenge_hash, request.challenge_chain_sp)
        assert ((quality_string is not None) and (len(quality_string) == 32))
        aggregate_signature: G2Element = G2Element()
        block_generator: Optional[BlockGenerator] = None
        additions: Optional[List[Coin]] = []
        removals: Optional[List[Coin]] = []
        async with self.full_node._blockchain_lock_high_priority:
            peak: Optional[BlockRecord] = self.full_node.blockchain.get_peak()
            if (peak is not None):
                curr_l_tb: BlockRecord = peak
                while (not curr_l_tb.is_transaction_block):
                    curr_l_tb = self.full_node.blockchain.block_record(curr_l_tb.prev_hash)
                try:
                    mempool_bundle = (await self.full_node.mempool_manager.create_bundle_from_mempool(curr_l_tb.header_hash))
                except Exception as e:
                    self.log.error(f'Traceback: {traceback.format_exc()}')
                    self.full_node.log.error(f'Error making spend bundle {e} peak: {peak}')
                    mempool_bundle = None
                if (mempool_bundle is not None):
                    spend_bundle = mempool_bundle[0]
                    additions = mempool_bundle[1]
                    removals = mempool_bundle[2]
                    self.full_node.log.info(f'Add rem: {len(additions)} {len(removals)}')
                    aggregate_signature = spend_bundle.aggregated_signature
                    if (self.full_node.full_node_store.previous_generator is not None):
                        self.log.info(f'Using previous generator for height {self.full_node.full_node_store.previous_generator}')
                        block_generator = best_solution_generator_from_template(self.full_node.full_node_store.previous_generator, spend_bundle)
                    else:
                        block_generator = simple_solution_generator(spend_bundle)

        def get_plot_sig(to_sign, _) -> G2Element:
            if (to_sign == request.challenge_chain_sp):
                return request.challenge_chain_sp_signature
            elif (to_sign == request.reward_chain_sp):
                return request.reward_chain_sp_signature
            return G2Element()

        def get_pool_sig(_1, _2) -> Optional[G2Element]:
            return request.pool_signature
        prev_b: Optional[BlockRecord] = self.full_node.blockchain.get_peak()
        if (prev_b is not None):
            if (request.signage_point_index == 0):
                if (pos_sub_slot is None):
                    self.log.warning('Pos sub slot is None')
                    return None
                rc_challenge = pos_sub_slot[0].reward_chain.end_of_slot_vdf.challenge
            else:
                assert (sp_vdfs.rc_vdf is not None)
                rc_challenge = sp_vdfs.rc_vdf.challenge
            for (eos, _, _) in reversed(self.full_node.full_node_store.finished_sub_slots):
                if ((eos is not None) and (eos.reward_chain.get_hash() == rc_challenge)):
                    rc_challenge = eos.reward_chain.end_of_slot_vdf.challenge
            found = False
            attempts = 0
            while ((prev_b is not None) and (attempts < 10)):
                if (prev_b.reward_infusion_new_challenge == rc_challenge):
                    found = True
                    break
                if ((prev_b.finished_reward_slot_hashes is not None) and (len(prev_b.finished_reward_slot_hashes) > 0)):
                    if (prev_b.finished_reward_slot_hashes[(- 1)] == rc_challenge):
                        prev_b = self.full_node.blockchain.try_block_record(prev_b.prev_hash)
                        found = True
                        break
                prev_b = self.full_node.blockchain.try_block_record(prev_b.prev_hash)
                attempts += 1
            if (not found):
                self.log.warning('Did not find a previous block with the correct reward chain hash')
                return None
        try:
            finished_sub_slots: Optional[List[EndOfSubSlotBundle]] = self.full_node.full_node_store.get_finished_sub_slots(self.full_node.blockchain, prev_b, cc_challenge_hash)
            if (finished_sub_slots is None):
                return None
            if ((len(finished_sub_slots) > 0) and (pos_sub_slot is not None) and (finished_sub_slots[(- 1)] != pos_sub_slot[0])):
                self.log.error('Have different sub-slots than is required to farm this block')
                return None
        except ValueError as e:
            self.log.warning(f'Value Error: {e}')
            return None
        if (prev_b is None):
            pool_target = PoolTarget(self.full_node.constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH, uint32(0))
            farmer_ph = self.full_node.constants.GENESIS_PRE_FARM_FARMER_PUZZLE_HASH
        else:
            farmer_ph = request.farmer_puzzle_hash
            if (request.proof_of_space.pool_contract_puzzle_hash is not None):
                pool_target = PoolTarget(request.proof_of_space.pool_contract_puzzle_hash, uint32(0))
            else:
                assert (request.pool_target is not None)
                pool_target = request.pool_target
        if ((peak is None) or (peak.height <= self.full_node.constants.MAX_SUB_SLOT_BLOCKS)):
            difficulty = self.full_node.constants.DIFFICULTY_STARTING
            sub_slot_iters = self.full_node.constants.SUB_SLOT_ITERS_STARTING
        else:
            difficulty = uint64((peak.weight - self.full_node.blockchain.block_record(peak.prev_hash).weight))
            sub_slot_iters = peak.sub_slot_iters
            for sub_slot in finished_sub_slots:
                if (sub_slot.challenge_chain.new_difficulty is not None):
                    difficulty = sub_slot.challenge_chain.new_difficulty
                if (sub_slot.challenge_chain.new_sub_slot_iters is not None):
                    sub_slot_iters = sub_slot.challenge_chain.new_sub_slot_iters
        required_iters: uint64 = calculate_iterations_quality(self.full_node.constants.DIFFICULTY_CONSTANT_FACTOR, quality_string, request.proof_of_space.size, difficulty, request.challenge_chain_sp)
        sp_iters: uint64 = calculate_sp_iters(self.full_node.constants, sub_slot_iters, request.signage_point_index)
        ip_iters: uint64 = calculate_ip_iters(self.full_node.constants, sub_slot_iters, request.signage_point_index, required_iters)
        timestamp = uint64(int(time.time()))
        curr: Optional[BlockRecord] = prev_b
        while ((curr is not None) and (not curr.is_transaction_block) and (curr.height != 0)):
            curr = self.full_node.blockchain.try_block_record(curr.prev_hash)
        if (curr is not None):
            assert (curr.timestamp is not None)
            if (timestamp <= curr.timestamp):
                timestamp = uint64(int((curr.timestamp + 1)))
        self.log.info('Starting to make the unfinished block')
        unfinished_block: UnfinishedBlock = create_unfinished_block(self.full_node.constants, total_iters_pos_slot, sub_slot_iters, request.signage_point_index, sp_iters, ip_iters, request.proof_of_space, cc_challenge_hash, farmer_ph, pool_target, get_plot_sig, get_pool_sig, sp_vdfs, timestamp, self.full_node.blockchain, b'', block_generator, aggregate_signature, additions, removals, prev_b, finished_sub_slots)
        self.log.info('Made the unfinished block')
        if (prev_b is not None):
            height: uint32 = uint32((prev_b.height + 1))
        else:
            height = uint32(0)
        self.full_node.full_node_store.add_candidate_block(quality_string, height, unfinished_block)
        foliage_sb_data_hash = unfinished_block.foliage.foliage_block_data.get_hash()
        if unfinished_block.is_transaction_block():
            foliage_transaction_block_hash = unfinished_block.foliage.foliage_transaction_block_hash
        else:
            foliage_transaction_block_hash = bytes32(([0] * 32))
        assert (foliage_transaction_block_hash is not None)
        message = farmer_protocol.RequestSignedValues(quality_string, foliage_sb_data_hash, foliage_transaction_block_hash)
        (await peer.send_message(make_msg(ProtocolMessageTypes.request_signed_values, message)))
        if (unfinished_block.is_transaction_block() and (unfinished_block.transactions_generator is not None)):
            unfinished_block_backup = create_unfinished_block(self.full_node.constants, total_iters_pos_slot, sub_slot_iters, request.signage_point_index, sp_iters, ip_iters, request.proof_of_space, cc_challenge_hash, farmer_ph, pool_target, get_plot_sig, get_pool_sig, sp_vdfs, timestamp, self.full_node.blockchain, b'', None, G2Element(), None, None, prev_b, finished_sub_slots)
            self.full_node.full_node_store.add_candidate_block(quality_string, height, unfinished_block_backup, backup=True)
    return None
Creates a block body and header, with the proof of space, coinbase, and fee targets provided
by the farmer, and sends the hash of the header data back to the farmer.
@api_request
@peer_required
async def declare_proof_of_space(self, request: farmer_protocol.DeclareProofOfSpace, peer: ws.WSChiaConnection) -> Optional[Message]:
    '\n        Creates a block body and header, with the proof of space, coinbase, and fee targets provided\n        by the farmer, and sends the hash of the header data back to the farmer.\n        '
    if self.full_node.sync_store.get_sync_mode():
        return None
    async with self.full_node.timelord_lock:
        sp_vdfs: Optional[SignagePoint] = self.full_node.full_node_store.get_signage_point(request.challenge_chain_sp)
        if (sp_vdfs is None):
            self.log.warning(f'Received proof of space for an unknown signage point {request.challenge_chain_sp}')
            return None
        if (request.signage_point_index > 0):
            assert (sp_vdfs.rc_vdf is not None)
            if (sp_vdfs.rc_vdf.output.get_hash() != request.reward_chain_sp):
                self.log.debug(f'Received proof of space for a potentially old signage point {request.challenge_chain_sp}. Current sp: {sp_vdfs.rc_vdf.output.get_hash()}')
                return None
        if (request.signage_point_index == 0):
            cc_challenge_hash: bytes32 = request.challenge_chain_sp
        else:
            assert (sp_vdfs.cc_vdf is not None)
            cc_challenge_hash = sp_vdfs.cc_vdf.challenge
        pos_sub_slot: Optional[Tuple[(EndOfSubSlotBundle, int, uint128)]] = None
        if (request.challenge_hash != self.full_node.constants.GENESIS_CHALLENGE):
            pos_sub_slot = self.full_node.full_node_store.get_sub_slot(cc_challenge_hash)
            if (pos_sub_slot is None):
                self.log.warning(f'Received proof of space for an unknown sub slot: {request}')
                return None
            total_iters_pos_slot: uint128 = pos_sub_slot[2]
        else:
            total_iters_pos_slot = uint128(0)
        assert (cc_challenge_hash == request.challenge_hash)
        quality_string: Optional[bytes32] = request.proof_of_space.verify_and_get_quality_string(self.full_node.constants, cc_challenge_hash, request.challenge_chain_sp)
        assert ((quality_string is not None) and (len(quality_string) == 32))
        aggregate_signature: G2Element = G2Element()
        block_generator: Optional[BlockGenerator] = None
        additions: Optional[List[Coin]] = []
        removals: Optional[List[Coin]] = []
        async with self.full_node._blockchain_lock_high_priority:
            peak: Optional[BlockRecord] = self.full_node.blockchain.get_peak()
            if (peak is not None):
                curr_l_tb: BlockRecord = peak
                while (not curr_l_tb.is_transaction_block):
                    curr_l_tb = self.full_node.blockchain.block_record(curr_l_tb.prev_hash)
                try:
                    mempool_bundle = (await self.full_node.mempool_manager.create_bundle_from_mempool(curr_l_tb.header_hash))
                except Exception as e:
                    self.log.error(f'Traceback: {traceback.format_exc()}')
                    self.full_node.log.error(f'Error making spend bundle {e} peak: {peak}')
                    mempool_bundle = None
                if (mempool_bundle is not None):
                    spend_bundle = mempool_bundle[0]
                    additions = mempool_bundle[1]
                    removals = mempool_bundle[2]
                    self.full_node.log.info(f'Add rem: {len(additions)} {len(removals)}')
                    aggregate_signature = spend_bundle.aggregated_signature
                    if (self.full_node.full_node_store.previous_generator is not None):
                        self.log.info(f'Using previous generator for height {self.full_node.full_node_store.previous_generator}')
                        block_generator = best_solution_generator_from_template(self.full_node.full_node_store.previous_generator, spend_bundle)
                    else:
                        block_generator = simple_solution_generator(spend_bundle)

        def get_plot_sig(to_sign, _) -> G2Element:
            if (to_sign == request.challenge_chain_sp):
                return request.challenge_chain_sp_signature
            elif (to_sign == request.reward_chain_sp):
                return request.reward_chain_sp_signature
            return G2Element()

        def get_pool_sig(_1, _2) -> Optional[G2Element]:
            return request.pool_signature
        prev_b: Optional[BlockRecord] = self.full_node.blockchain.get_peak()
        if (prev_b is not None):
            if (request.signage_point_index == 0):
                if (pos_sub_slot is None):
                    self.log.warning('Pos sub slot is None')
                    return None
                rc_challenge = pos_sub_slot[0].reward_chain.end_of_slot_vdf.challenge
            else:
                assert (sp_vdfs.rc_vdf is not None)
                rc_challenge = sp_vdfs.rc_vdf.challenge
            for (eos, _, _) in reversed(self.full_node.full_node_store.finished_sub_slots):
                if ((eos is not None) and (eos.reward_chain.get_hash() == rc_challenge)):
                    rc_challenge = eos.reward_chain.end_of_slot_vdf.challenge
            found = False
            attempts = 0
            while ((prev_b is not None) and (attempts < 10)):
                if (prev_b.reward_infusion_new_challenge == rc_challenge):
                    found = True
                    break
                if ((prev_b.finished_reward_slot_hashes is not None) and (len(prev_b.finished_reward_slot_hashes) > 0)):
                    if (prev_b.finished_reward_slot_hashes[(- 1)] == rc_challenge):
                        prev_b = self.full_node.blockchain.try_block_record(prev_b.prev_hash)
                        found = True
                        break
                prev_b = self.full_node.blockchain.try_block_record(prev_b.prev_hash)
                attempts += 1
            if (not found):
                self.log.warning('Did not find a previous block with the correct reward chain hash')
                return None
        try:
            finished_sub_slots: Optional[List[EndOfSubSlotBundle]] = self.full_node.full_node_store.get_finished_sub_slots(self.full_node.blockchain, prev_b, cc_challenge_hash)
            if (finished_sub_slots is None):
                return None
            if ((len(finished_sub_slots) > 0) and (pos_sub_slot is not None) and (finished_sub_slots[(- 1)] != pos_sub_slot[0])):
                self.log.error('Have different sub-slots than is required to farm this block')
                return None
        except ValueError as e:
            self.log.warning(f'Value Error: {e}')
            return None
        if (prev_b is None):
            pool_target = PoolTarget(self.full_node.constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH, uint32(0))
            farmer_ph = self.full_node.constants.GENESIS_PRE_FARM_FARMER_PUZZLE_HASH
        else:
            farmer_ph = request.farmer_puzzle_hash
            if (request.proof_of_space.pool_contract_puzzle_hash is not None):
                pool_target = PoolTarget(request.proof_of_space.pool_contract_puzzle_hash, uint32(0))
            else:
                assert (request.pool_target is not None)
                pool_target = request.pool_target
        if ((peak is None) or (peak.height <= self.full_node.constants.MAX_SUB_SLOT_BLOCKS)):
            difficulty = self.full_node.constants.DIFFICULTY_STARTING
            sub_slot_iters = self.full_node.constants.SUB_SLOT_ITERS_STARTING
        else:
            difficulty = uint64((peak.weight - self.full_node.blockchain.block_record(peak.prev_hash).weight))
            sub_slot_iters = peak.sub_slot_iters
            for sub_slot in finished_sub_slots:
                if (sub_slot.challenge_chain.new_difficulty is not None):
                    difficulty = sub_slot.challenge_chain.new_difficulty
                if (sub_slot.challenge_chain.new_sub_slot_iters is not None):
                    sub_slot_iters = sub_slot.challenge_chain.new_sub_slot_iters
        required_iters: uint64 = calculate_iterations_quality(self.full_node.constants.DIFFICULTY_CONSTANT_FACTOR, quality_string, request.proof_of_space.size, difficulty, request.challenge_chain_sp)
        sp_iters: uint64 = calculate_sp_iters(self.full_node.constants, sub_slot_iters, request.signage_point_index)
        ip_iters: uint64 = calculate_ip_iters(self.full_node.constants, sub_slot_iters, request.signage_point_index, required_iters)
        timestamp = uint64(int(time.time()))
        curr: Optional[BlockRecord] = prev_b
        while ((curr is not None) and (not curr.is_transaction_block) and (curr.height != 0)):
            curr = self.full_node.blockchain.try_block_record(curr.prev_hash)
        if (curr is not None):
            assert (curr.timestamp is not None)
            if (timestamp <= curr.timestamp):
                timestamp = uint64(int((curr.timestamp + 1)))
        self.log.info('Starting to make the unfinished block')
        unfinished_block: UnfinishedBlock = create_unfinished_block(self.full_node.constants, total_iters_pos_slot, sub_slot_iters, request.signage_point_index, sp_iters, ip_iters, request.proof_of_space, cc_challenge_hash, farmer_ph, pool_target, get_plot_sig, get_pool_sig, sp_vdfs, timestamp, self.full_node.blockchain, b, block_generator, aggregate_signature, additions, removals, prev_b, finished_sub_slots)
        self.log.info('Made the unfinished block')
        if (prev_b is not None):
            height: uint32 = uint32((prev_b.height + 1))
        else:
            height = uint32(0)
        self.full_node.full_node_store.add_candidate_block(quality_string, height, unfinished_block)
        foliage_sb_data_hash = unfinished_block.foliage.foliage_block_data.get_hash()
        if unfinished_block.is_transaction_block():
            foliage_transaction_block_hash = unfinished_block.foliage.foliage_transaction_block_hash
        else:
            foliage_transaction_block_hash = bytes32(([0] * 32))
        assert (foliage_transaction_block_hash is not None)
        message = farmer_protocol.RequestSignedValues(quality_string, foliage_sb_data_hash, foliage_transaction_block_hash)
        (await peer.send_message(make_msg(ProtocolMessageTypes.request_signed_values, message)))
        if (unfinished_block.is_transaction_block() and (unfinished_block.transactions_generator is not None)):
            unfinished_block_backup = create_unfinished_block(self.full_node.constants, total_iters_pos_slot, sub_slot_iters, request.signage_point_index, sp_iters, ip_iters, request.proof_of_space, cc_challenge_hash, farmer_ph, pool_target, get_plot_sig, get_pool_sig, sp_vdfs, timestamp, self.full_node.blockchain, b, None, G2Element(), None, None, prev_b, finished_sub_slots)
            self.full_node.full_node_store.add_candidate_block(quality_string, height, unfinished_block_backup, backup=True)
    return None