Ejemplo n.º 1
0
async def wallet_next_block_check(
    peer: WSChiaConnection, potential_peek: uint32, blockchain: BlockchainInterface
) -> bool:
    block_response = await peer.request_header_blocks(
        wallet_protocol.RequestHeaderBlocks(potential_peek, potential_peek)
    )
    if block_response is not None and isinstance(block_response, wallet_protocol.RespondHeaderBlocks):
        our_peak = blockchain.get_peak()
        if our_peak is not None and block_response.header_blocks[0].prev_header_hash == our_peak.header_hash:
            return True
    return False
Ejemplo n.º 2
0
    async def _sync(self) -> None:
        """
        Wallet has fallen far behind (or is starting up for the first time), and must be synced
        up to the LCA of the blockchain.
        """
        if self.wallet_state_manager is None or self.backup_initialized is False or self.server is None:
            return None

        highest_weight: uint128 = uint128(0)
        peak_height: uint32 = uint32(0)
        peak: Optional[HeaderBlock] = None
        potential_peaks: List[
            Tuple[bytes32, HeaderBlock]
        ] = self.wallet_state_manager.sync_store.get_potential_peaks_tuples()

        self.log.info(f"Have collected {len(potential_peaks)} potential peaks")

        for header_hash, potential_peak_block in potential_peaks:
            if potential_peak_block.weight > highest_weight:
                highest_weight = potential_peak_block.weight
                peak_height = potential_peak_block.height
                peak = potential_peak_block

        if peak_height is None or peak_height == 0:
            return None

        if self.wallet_state_manager.peak is not None and highest_weight <= self.wallet_state_manager.peak.weight:
            self.log.info("Not performing sync, already caught up.")
            return None

        peers: List[WSChiaConnection] = self.server.get_full_node_connections()
        if len(peers) == 0:
            self.log.info("No peers to sync to")
            return None

        async with self.wallet_state_manager.blockchain.lock:
            fork_height = None
            if peak is not None:
                fork_height = self.wallet_state_manager.sync_store.get_potential_fork_point(peak.header_hash)
                our_peak_height = self.wallet_state_manager.blockchain.get_peak_height()
                ses_heigths = self.wallet_state_manager.blockchain.get_ses_heights()
                if len(ses_heigths) > 2 and our_peak_height is not None:
                    ses_heigths.sort()
                    max_fork_ses_height = ses_heigths[-3]
                    # This is the fork point in SES in the case where no fork was detected
                    if (
                        self.wallet_state_manager.blockchain.get_peak_height() is not None
                        and fork_height == max_fork_ses_height
                    ):
                        peers = self.server.get_full_node_connections()
                        for peer in peers:
                            # Grab a block at peak + 1 and check if fork point is actually our current height
                            potential_height = uint32(our_peak_height + 1)
                            block_response: Optional[Any] = await peer.request_header_blocks(
                                wallet_protocol.RequestHeaderBlocks(potential_height, potential_height)
                            )
                            if block_response is not None and isinstance(
                                block_response, wallet_protocol.RespondHeaderBlocks
                            ):
                                our_peak = self.wallet_state_manager.blockchain.get_peak()
                                if (
                                    our_peak is not None
                                    and block_response.header_blocks[0].prev_header_hash == our_peak.header_hash
                                ):
                                    fork_height = our_peak_height
                                break
            if fork_height is None:
                fork_height = uint32(0)
            await self.wallet_state_manager.blockchain.warmup(fork_height)
            batch_size = self.constants.MAX_BLOCK_COUNT_PER_REQUESTS
            advanced_peak = False
            for i in range(max(0, fork_height - 1), peak_height, batch_size):
                start_height = i
                end_height = min(peak_height, start_height + batch_size)
                peers = self.server.get_full_node_connections()
                added = False
                for peer in peers:
                    try:
                        added, advanced_peak = await self.fetch_blocks_and_validate(
                            peer, uint32(start_height), uint32(end_height), None if advanced_peak else fork_height
                        )
                        if added:
                            break
                    except Exception as e:
                        await peer.close()
                        exc = traceback.format_exc()
                        self.log.error(f"Error while trying to fetch from peer:{e} {exc}")
                if not added:
                    raise RuntimeError(f"Was not able to add blocks {start_height}-{end_height}")

                peak = self.wallet_state_manager.blockchain.get_peak()
                assert peak is not None
                self.wallet_state_manager.blockchain.clean_block_record(
                    min(
                        end_height - self.constants.BLOCKS_CACHE_SIZE,
                        peak.height - self.constants.BLOCKS_CACHE_SIZE,
                    )
                )
Ejemplo n.º 3
0
    async def _sync(self) -> None:
        """
        Wallet has fallen far behind (or is starting up for the first time), and must be synced
        up to the LCA of the blockchain.
        """
        if self.wallet_state_manager is None or self.backup_initialized is False or self.server is None:
            return None

        highest_weight: uint128 = uint128(0)
        peak_height: uint32 = uint32(0)
        peak: Optional[HeaderBlock] = None
        potential_peaks: List[
            Tuple[bytes32, HeaderBlock]
        ] = self.wallet_state_manager.sync_store.get_potential_peaks_tuples()

        self.log.info(f"Have collected {len(potential_peaks)} potential peaks")

        for header_hash, potential_peak_block in potential_peaks:
            if potential_peak_block.weight > highest_weight:
                highest_weight = potential_peak_block.weight
                peak_height = potential_peak_block.height
                peak = potential_peak_block

        if peak_height is None or peak_height == 0:
            return None

        if self.wallet_state_manager.peak is not None and highest_weight <= self.wallet_state_manager.peak.weight:
            self.log.info("Not performing sync, already caught up.")
            return None

        peers: List[WSChiaConnection] = self.server.get_full_node_connections()
        if len(peers) == 0:
            self.log.info("No peers to sync to")
            return None

        async with self.wallet_state_manager.blockchain.lock:
            fork_height = None
            if peak is not None:
                fork_height = self.wallet_state_manager.sync_store.get_potential_fork_point(peak.header_hash)
                our_peak_height = self.wallet_state_manager.blockchain.get_peak_height()
                ses_heigths = self.wallet_state_manager.blockchain.get_ses_heights()
                if len(ses_heigths) > 2 and our_peak_height is not None:
                    ses_heigths.sort()
                    max_fork_ses_height = ses_heigths[-3]
                    # This is the fork point in SES in the case where no fork was detected
                    if (
                        self.wallet_state_manager.blockchain.get_peak_height() is not None
                        and fork_height == max_fork_ses_height
                    ):
                        peers = self.server.get_full_node_connections()
                        for peer in peers:
                            # Grab a block at peak + 1 and check if fork point is actually our current height
                            potential_height = uint32(our_peak_height + 1)
                            block_response: Optional[Any] = await peer.request_header_blocks(
                                wallet_protocol.RequestHeaderBlocks(potential_height, potential_height)
                            )
                            if block_response is not None and isinstance(
                                block_response, wallet_protocol.RespondHeaderBlocks
                            ):
                                our_peak = self.wallet_state_manager.blockchain.get_peak()
                                if (
                                    our_peak is not None
                                    and block_response.header_blocks[0].prev_header_hash == our_peak.header_hash
                                ):
                                    fork_height = our_peak_height
                                break
            if fork_height is None:
                fork_height = uint32(0)
            await self.wallet_state_manager.blockchain.warmup(fork_height)
            await self.batch_sync_to_peak(fork_height, peak)
            )),
        bytes(b"a" * 10),
        bytes(b"a" * 10),
    )],
)

reject_additions = wallet_protocol.RejectAdditionsRequest(
    uint32(3457211200),
    bytes32(
        bytes.fromhex(
            "4eb659e6dd727bc22191795692aae576922e56ae309871c352eede0c9dd8bb12")
    ),
)

request_header_blocks = wallet_protocol.RequestHeaderBlocks(
    uint32(2858301848),
    uint32(720941539),
)

reject_header_blocks = wallet_protocol.RejectHeaderBlocks(
    uint32(876520264),
    uint32(2908717391),
)

respond_header_blocks = wallet_protocol.RespondHeaderBlocks(
    uint32(4130100992),
    uint32(17664086),
    [header_block],
)

coin_state = wallet_protocol.CoinState(
    coin_1,