예제 #1
0
 async def wallet_short_sync_backtrack(self, header_block, peer):
     top = header_block
     blocks = [top]
     # Fetch blocks backwards until we hit the one that we have,
     # then complete them with additions / removals going forward
     while not self.wallet_state_manager.blockchain.contains_block(top.prev_header_hash) and top.height > 0:
         request_prev = wallet_protocol.RequestBlockHeader(top.height - 1)
         response_prev: Optional[RespondBlockHeader] = await peer.request_block_header(request_prev)
         if response_prev is None or not isinstance(response_prev, RespondBlockHeader):
             raise RuntimeError("bad block header response from peer while syncing")
         prev_head = response_prev.header_block
         blocks.append(prev_head)
         top = prev_head
     blocks.reverse()
     await self.complete_blocks(blocks, peer)
     await self.wallet_state_manager.create_more_puzzle_hashes()
예제 #2
0
    async def new_peak_wallet(self, peak: wallet_protocol.NewPeakWallet, peer: WSChiaConnection):
        if self.wallet_state_manager is None:
            return None

        curr_peak = self.wallet_state_manager.blockchain.get_peak()
        if curr_peak is not None and curr_peak.weight >= peak.weight:
            return None
        if self.new_peak_lock is None:
            self.new_peak_lock = asyncio.Lock()
        async with self.new_peak_lock:
            request = wallet_protocol.RequestBlockHeader(peak.height)
            response: Optional[RespondBlockHeader] = await peer.request_block_header(request)

            if response is None or not isinstance(response, RespondBlockHeader) or response.header_block is None:
                return None

            header_block = response.header_block

            if (curr_peak is None and header_block.height < self.constants.WEIGHT_PROOF_RECENT_BLOCKS) or (
                curr_peak is not None and curr_peak.height > header_block.height - 200
            ):
                top = header_block
                blocks = [top]
                # Fetch blocks backwards until we hit the one that we have,
                # then complete them with additions / removals going forward
                while not self.wallet_state_manager.blockchain.contains_block(top.prev_header_hash) and top.height > 0:
                    request_prev = wallet_protocol.RequestBlockHeader(top.height - 1)
                    response_prev: Optional[RespondBlockHeader] = await peer.request_block_header(request_prev)
                    if response_prev is None:
                        return None
                    if not isinstance(response_prev, RespondBlockHeader):
                        return None
                    prev_head = response_prev.header_block
                    blocks.append(prev_head)
                    top = prev_head
                blocks.reverse()
                await self.complete_blocks(blocks, peer)
                await self.wallet_state_manager.create_more_puzzle_hashes()
            elif header_block.height >= self.constants.WEIGHT_PROOF_RECENT_BLOCKS:
                # Request weight proof
                # Sync if PoW validates
                if self.wallet_state_manager.sync_mode:
                    self.last_new_peak_messages.put(peer, peak)
                    return None
                weight_request = RequestProofOfWeight(header_block.height, header_block.header_hash)
                weight_proof_response: RespondProofOfWeight = await peer.request_proof_of_weight(
                    weight_request, timeout=360
                )
                if weight_proof_response is None:
                    return None
                weight_proof = weight_proof_response.wp
                if self.wallet_state_manager is None:
                    return None
                if self.server is not None and self.server.is_trusted_peer(peer, self.config["trusted_peers"]):
                    valid, fork_point = self.wallet_state_manager.weight_proof_handler.get_fork_point_no_validations(
                        weight_proof
                    )
                else:
                    valid, fork_point, _ = await self.wallet_state_manager.weight_proof_handler.validate_weight_proof(
                        weight_proof
                    )
                    if not valid:
                        self.log.error(
                            f"invalid weight proof, num of epochs {len(weight_proof.sub_epochs)}"
                            f" recent blocks num ,{len(weight_proof.recent_chain_data)}"
                        )
                        self.log.debug(f"{weight_proof}")
                        return None
                self.log.info(f"Validated, fork point is {fork_point}")
                self.wallet_state_manager.sync_store.add_potential_fork_point(
                    header_block.header_hash, uint32(fork_point)
                )
                self.wallet_state_manager.sync_store.add_potential_peak(header_block)
                self.start_sync()
예제 #3
0
    async def new_peak_wallet(self, peak: wallet_protocol.NewPeakWallet, peer: WSChiaConnection):
        if self.wallet_state_manager is None:
            return

        if self.wallet_state_manager.blockchain.contains_block(peak.header_hash):
            self.log.debug(f"known peak {peak.header_hash}")
            return

        if self.wallet_state_manager.sync_mode:
            self.last_new_peak_messages.put(peer, peak)
            return

        async with self.new_peak_lock:
            curr_peak = self.wallet_state_manager.blockchain.get_peak()
            if curr_peak is not None and curr_peak.weight >= peak.weight:
                return

            request = wallet_protocol.RequestBlockHeader(peak.height)
            response: Optional[RespondBlockHeader] = await peer.request_block_header(request)
            if response is None or not isinstance(response, RespondBlockHeader) or response.header_block is None:
                self.log.warning(f"bad peak response from peer {response}")
                return
            header_block = response.header_block
            curr_peak_height = 0 if curr_peak is None else curr_peak.height
            if (curr_peak_height == 0 and peak.height < self.constants.WEIGHT_PROOF_RECENT_BLOCKS) or (
                curr_peak_height > peak.height - 200
            ):

                if peak.height <= curr_peak_height + self.config["short_sync_blocks_behind_threshold"]:
                    await self.wallet_short_sync_backtrack(header_block, peer)
                else:
                    await self.batch_sync_to_peak(curr_peak_height, peak)
            elif peak.height >= self.constants.WEIGHT_PROOF_RECENT_BLOCKS:
                # Request weight proof
                # Sync if PoW validates
                weight_request = RequestProofOfWeight(peak.height, peak.header_hash)
                weight_proof_response: RespondProofOfWeight = await peer.request_proof_of_weight(
                    weight_request, timeout=360
                )
                if weight_proof_response is None:
                    return

                weight_proof = weight_proof_response.wp
                if self.wallet_state_manager is None:
                    return
                if self.server is not None and self.server.is_trusted_peer(peer, self.config["trusted_peers"]):
                    valid, fork_point = self.wallet_state_manager.weight_proof_handler.get_fork_point_no_validations(
                        weight_proof
                    )
                else:
                    valid, fork_point, _ = await self.wallet_state_manager.weight_proof_handler.validate_weight_proof(
                        weight_proof
                    )
                if not valid:
                    self.log.error(
                        f"invalid weight proof, num of epochs {len(weight_proof.sub_epochs)}"
                        f" recent blocks num ,{len(weight_proof.recent_chain_data)}"
                    )
                    self.log.debug(f"{weight_proof}")
                    return
                self.log.info(f"Validated, fork point is {fork_point}")
                self.wallet_state_manager.sync_store.add_potential_fork_point(
                    header_block.header_hash, uint32(fork_point)
                )
                self.wallet_state_manager.sync_store.add_potential_peak(header_block)
                self.start_sync()
    ),
    uint8(30),
    "None",
)

new_peak_wallet = wallet_protocol.NewPeakWallet(
    bytes32(
        bytes.fromhex(
            "ee50e45652cb6a60e3ab0031aa425a6019648fe5344ae860e6fc14af1aa3c2fa")
    ),
    uint32(1093428752),
    uint128(207496292293729126634170184354599452208),
    uint32(133681371),
)

request_block_header = wallet_protocol.RequestBlockHeader(uint32(3562957314), )

respond_header_block = wallet_protocol.RespondBlockHeader(header_block, )

reject_header_request = wallet_protocol.RejectHeaderRequest(uint32(17867635), )

request_removals = wallet_protocol.RequestRemovals(
    uint32(3500751918),
    bytes32(
        bytes.fromhex(
            "b44bc0e0fce20331a57081107dfd30ef39fc436e6e6ce4f6f0ab8db4f981d114")
    ),
    [
        bytes32(
            bytes.fromhex(
                "ab62cfb2abaf9e1a475b707c3d3de35d6ef4a298b31137802fd9ea47d48ff0d5"