Пример #1
0
    async def generate_login_link(self, launcher_id: bytes32) -> Optional[str]:
        for pool_state in self.pool_state.values():
            pool_config: PoolWalletConfig = pool_state["pool_config"]
            if pool_config.launcher_id == launcher_id:
                authentication_sk: Optional[PrivateKey] = await find_authentication_sk(
                    self.all_root_sks, pool_config.authentication_public_key
                )
                if authentication_sk is None:
                    self.log.error(f"Could not find authentication sk for pk: {pool_config.authentication_public_key}")
                    continue
                assert authentication_sk.get_g1() == pool_config.authentication_public_key
                authentication_token_timeout = pool_state["authentication_token_timeout"]
                authentication_token = get_current_authentication_token(authentication_token_timeout)
                message: bytes32 = std_hash(
                    AuthenticationPayload(
                        "get_login", pool_config.launcher_id, pool_config.target_puzzle_hash, authentication_token
                    )
                )
                signature: G2Element = AugSchemeMPL.sign(authentication_sk, message)
                return (
                    pool_config.pool_url
                    + f"/login?launcher_id={launcher_id.hex()}&authentication_token={authentication_token}"
                    f"&signature={bytes(signature).hex()}"
                )

        return None
Пример #2
0
    async def get_login(self, request_obj) -> web.Response:
        # TODO(pool): add rate limiting
        launcher_id: bytes32 = hexstr_to_bytes(
            request_obj.rel_url.query["launcher_id"])
        authentication_token: uint64 = uint64(
            request_obj.rel_url.query["authentication_token"])
        authentication_token_error = check_authentication_token(
            launcher_id, authentication_token,
            self.pool.authentication_token_timeout)
        if authentication_token_error is not None:
            return authentication_token_error

        farmer_record: Optional[
            FarmerRecord] = await self.pool.store.get_farmer_record(launcher_id
                                                                    )
        if farmer_record is None:
            return error_response(
                PoolErrorCode.FARMER_NOT_KNOWN,
                f"Farmer with launcher_id {launcher_id.hex()} unknown.")

        # Validate provided signature
        signature: G2Element = G2Element.from_bytes(
            hexstr_to_bytes(request_obj.rel_url.query["signature"]))
        message: bytes32 = std_hash(
            AuthenticationPayload("get_login", launcher_id,
                                  self.pool.default_target_puzzle_hash,
                                  authentication_token))
        if not AugSchemeMPL.verify(farmer_record.authentication_public_key,
                                   message, signature):
            return error_response(
                PoolErrorCode.INVALID_SIGNATURE,
                f"Failed to verify signature {signature} for launcher_id {launcher_id.hex()}.",
            )

        self.pool.log.info(
            f"Login successful for launcher_id: {launcher_id.hex()}")

        record: Optional[
            FarmerRecord] = await self.pool.store.get_farmer_record(launcher_id
                                                                    )
        response = {}
        if record is not None:
            response["farmer_record"] = record
            recent_partials = await self.pool.store.get_recent_partials(
                launcher_id, 20)
            response["recent_partials"] = recent_partials

        # TODO(pool) Do what ever you like with the successful login
        return obj_to_response(response)
Пример #3
0
    async def get_farmer(self, request_obj) -> web.Response:
        # TODO(pool): add rate limiting
        launcher_id: bytes32 = hexstr_to_bytes(
            request_obj.rel_url.query["launcher_id"])
        authentication_token = uint64(
            request_obj.rel_url.query["authentication_token"])

        authentication_token_error: Optional[
            web.Response] = check_authentication_token(
                launcher_id, authentication_token,
                self.pool.authentication_token_timeout)
        if authentication_token_error is not None:
            return authentication_token_error

        farmer_record: Optional[
            FarmerRecord] = await self.pool.store.get_farmer_record(launcher_id
                                                                    )
        if farmer_record is None:
            return error_response(
                PoolErrorCode.FARMER_NOT_KNOWN,
                f"Farmer with launcher_id {launcher_id.hex()} unknown.")

        # Validate provided signature
        signature: G2Element = G2Element.from_bytes(
            hexstr_to_bytes(request_obj.rel_url.query["signature"]))
        message: bytes32 = std_hash(
            AuthenticationPayload("get_farmer", launcher_id,
                                  self.pool.default_target_puzzle_hash,
                                  authentication_token))
        if not AugSchemeMPL.verify(farmer_record.authentication_public_key,
                                   message, signature):
            return error_response(
                PoolErrorCode.INVALID_SIGNATURE,
                f"Failed to verify signature {signature} for launcher_id {launcher_id.hex()}.",
            )

        response: GetFarmerResponse = GetFarmerResponse(
            farmer_record.authentication_public_key,
            farmer_record.payout_instructions,
            farmer_record.difficulty,
            farmer_record.points,
        )

        self.pool.log.info(f"get_farmer response {response.to_json_dict()}, "
                           f"launcher_id: {launcher_id.hex()}")
        return obj_to_response(response)
Пример #4
0
 async def _pool_get_farmer(
         self, pool_config: PoolWalletConfig,
         authentication_token_timeout: uint8,
         authentication_sk: PrivateKey) -> Optional[Dict]:
     assert authentication_sk.get_g1(
     ) == pool_config.authentication_public_key
     authentication_token = get_current_authentication_token(
         authentication_token_timeout)
     message: bytes32 = std_hash(
         AuthenticationPayload("get_farmer", pool_config.launcher_id,
                               pool_config.target_puzzle_hash,
                               authentication_token))
     signature: G2Element = AugSchemeMPL.sign(authentication_sk, message)
     get_farmer_params = {
         "launcher_id": pool_config.launcher_id.hex(),
         "authentication_token": authentication_token,
         "signature": bytes(signature).hex(),
     }
     try:
         async with aiohttp.ClientSession(trust_env=True) as session:
             async with session.get(
                     f"{pool_config.pool_url}/farmer",
                     params=get_farmer_params,
                     ssl=ssl_context_for_root(get_mozilla_ca_crt(),
                                              log=self.log),
             ) as resp:
                 if resp.ok:
                     response: Dict = json.loads(await resp.text())
                     self.log.info(f"GET /farmer response: {response}")
                     if "error_code" in response:
                         self.pool_state[
                             pool_config.p2_singleton_puzzle_hash][
                                 "pool_errors_24h"].append(response)
                     return response
                 else:
                     self.handle_failed_pool_response(
                         pool_config.p2_singleton_puzzle_hash,
                         f"Error in GET /farmer {pool_config.pool_url}, {resp.status}",
                     )
     except Exception as e:
         self.handle_failed_pool_response(
             pool_config.p2_singleton_puzzle_hash,
             f"Exception in GET /farmer {pool_config.pool_url}, {e}")
     return None