Пример #1
0
    def replace_str_to_bytes(self, **changes) -> "ConsensusConstants":
        """
        Overrides str (hex) values with bytes.
        """

        for k, v in changes.items():
            if isinstance(v, str):
                changes[k] = hexstr_to_bytes(v)

        return dataclasses.replace(self, **changes)
Пример #2
0
    async def get_mempool_item_by_tx_id(self, request: Dict) -> Optional[Dict]:
        if "tx_id" not in request:
            raise ValueError("No tx_id in request")
        tx_id: bytes32 = hexstr_to_bytes(request["tx_id"])

        item = self.service.mempool_manager.get_mempool_item(tx_id)
        if item is None:
            raise ValueError(f"Tx id 0x{tx_id.hex()} not in the mempool")

        return {"mempool_item": item}
Пример #3
0
async def get_transaction(args: dict, wallet_client: WalletRpcClient,
                          fingerprint: int) -> None:
    wallet_id = args["id"]
    transaction_id = hexstr_to_bytes(args["tx_id"])
    config = load_config(DEFAULT_ROOT_PATH, "config.yaml", SERVICE_NAME)
    name = config["network_overrides"]["config"][
        config["selected_network"]]["address_prefix"]
    tx: TransactionRecord = await wallet_client.get_transaction(
        wallet_id, transaction_id=transaction_id)
    print_transaction(tx, verbose=(args["verbose"] > 0), name=name)
Пример #4
0
    async def get_block(self, request: Dict) -> Optional[Dict]:
        if "header_hash" not in request:
            raise ValueError("No header_hash in request")
        header_hash = hexstr_to_bytes(request["header_hash"])

        block: Optional[FullBlock] = await self.service.block_store.get_full_block(header_hash)
        if block is None:
            raise ValueError(f"Block {header_hash.hex()} not found")

        return {"block": block}
Пример #5
0
 async def did_create_attest(self, request):
     wallet_id = int(request["wallet_id"])
     wallet: DIDWallet = self.service.wallet_state_manager.wallets[
         wallet_id]
     async with self.service.wallet_state_manager.lock:
         info = await wallet.get_info_for_recovery()
         coin = hexstr_to_bytes(request["coin_name"])
         pubkey = G1Element.from_bytes(hexstr_to_bytes(request["pubkey"]))
         spend_bundle = await wallet.create_attestment(
             coin, hexstr_to_bytes(request["puzhash"]), pubkey,
             request["filename"])
     if spend_bundle is not None:
         return {
             "success": True,
             "message_spend_bundle": bytes(spend_bundle).hex(),
             "info": [info[0].hex(), info[1].hex(), info[2]],
         }
     else:
         return {"success": False}
Пример #6
0
 async def get_connections(self,
                           node_type: Optional[NodeType] = None
                           ) -> List[Dict]:
     request = {}
     if node_type is not None:
         request["node_type"] = node_type.value
     response = await self.fetch("get_connections", request)
     for connection in response["connections"]:
         connection["node_id"] = hexstr_to_bytes(connection["node_id"])
     return response["connections"]
Пример #7
0
    async def get_transaction(self, request: Dict) -> Dict:
        assert self.service.wallet_state_manager is not None
        transaction_id: bytes32 = bytes32(hexstr_to_bytes(request["transaction_id"]))
        tr: Optional[TransactionRecord] = await self.service.wallet_state_manager.get_transaction(transaction_id)
        if tr is None:
            raise ValueError(f"Transaction 0x{transaction_id.hex()} not found")

        return {
            "transaction": tr,
            "transaction_id": tr.name,
        }
Пример #8
0
    async def cancel_trade(self, request: Dict):
        assert self.service.wallet_state_manager is not None

        wsm = self.service.wallet_state_manager
        secure = request["secure"]
        trade_id = hexstr_to_bytes(request["trade_id"])

        if secure:
            await wsm.trade_manager.cancel_pending_offer_safely(trade_id)
        else:
            await wsm.trade_manager.cancel_pending_offer(trade_id)
        return {}
Пример #9
0
async def create(args: dict, wallet_client: WalletRpcClient,
                 fingerprint: int) -> None:
    state = args["state"]
    prompt = not args.get("yes", False)

    # Could use initial_pool_state_from_dict to simplify
    if state == "SELF_POOLING":
        pool_url: Optional[str] = None
        relative_lock_height = uint32(0)
        target_puzzle_hash = None  # wallet will fill this in
    elif state == "FARMING_TO_POOL":
        pool_url = str(args["pool_url"])
        json_dict = await create_pool_args(pool_url)
        relative_lock_height = json_dict["relative_lock_height"]
        target_puzzle_hash = hexstr_to_bytes(json_dict["target_puzzle_hash"])
    else:
        raise ValueError(
            "Plot NFT must be created in SELF_POOLING or FARMING_TO_POOL state."
        )

    pool_msg = f" and join pool: {pool_url}" if pool_url else ""
    print(f"Will create a plot NFT{pool_msg}.")
    if prompt:
        user_input: str = input("Confirm [n]/y: ")
    else:
        user_input = "yes"

    if user_input.lower() == "y" or user_input.lower() == "yes":
        try:
            tx_record: TransactionRecord = await wallet_client.create_new_pool_wallet(
                target_puzzle_hash,
                pool_url,
                relative_lock_height,
                "localhost:5000",
                "new",
                state,
            )
            start = time.time()
            while time.time() - start < 10:
                await asyncio.sleep(0.1)
                tx = await wallet_client.get_transaction(
                    str(1), tx_record.name)
                if len(tx.sent_to) > 0:
                    print(f"Transaction submitted to nodes: {tx.sent_to}")
                    print(
                        f"Do chia wallet get_transaction -f {fingerprint} -tx 0x{tx_record.name} to get status"
                    )
                    return None
        except Exception as e:
            print(f"Error creating plot NFT: {e}")
        return
    print("Aborting.")
Пример #10
0
    async def get_coin_record_by_name(self, request: Dict) -> Optional[Dict]:
        """
        Retrieves a coin record by it's name.
        """
        if "name" not in request:
            raise ValueError("Name not in request")
        name = hexstr_to_bytes(request["name"])

        coin_record: Optional[CoinRecord] = await self.service.blockchain.coin_store.get_coin_record(name)
        if coin_record is None:
            raise ValueError(f"Coin record 0x{name.hex()} not found")

        return {"coin_record": coin_record}
Пример #11
0
    async def get_block_record(self, request: Dict):
        if "header_hash" not in request:
            raise ValueError("header_hash not in request")
        header_hash_str = request["header_hash"]
        header_hash = hexstr_to_bytes(header_hash_str)
        record: Optional[BlockRecord] = self.service.blockchain.try_block_record(header_hash)
        if record is None:
            # Fetch from DB
            record = await self.service.blockchain.block_store.get_block_record(header_hash)
        if record is None:
            raise ValueError(f"Block {header_hash.hex()} does not exist")

        return {"block_record": record}
Пример #12
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()}")

        return await self.login_response(launcher_id)
Пример #13
0
    async def get_object(self, key: str, type: Any) -> Any:
        """
        Return bytes representation of stored object
        """

        cursor = await self.db_connection.execute(
            "SELECT * from key_val_store WHERE key=?", (key, ))
        row = await cursor.fetchone()
        await cursor.close()

        if row is None:
            return None

        return type.from_bytes(hexstr_to_bytes(row[1]))
Пример #14
0
 async def close_connection(self, request: Dict):
     node_id = hexstr_to_bytes(request["node_id"])
     if self.rpc_api.service.server is None:
         raise aiohttp.web.HTTPInternalServerError()
     connections_to_close = [
         c for c in self.rpc_api.service.server.get_connections()
         if c.peer_node_id == node_id
     ]
     if len(connections_to_close) == 0:
         raise ValueError(
             f"Connection with node_id {node_id.hex()} does not exist")
     for connection in connections_to_close:
         await connection.close()
     return {}
Пример #15
0
def dataclass_from_dict(klass, d):
    """
    Converts a dictionary based on a dataclass, into an instance of that dataclass.
    Recursively goes through lists, optionals, and dictionaries.
    """
    if is_type_SpecificOptional(klass):
        # Type is optional, data is either None, or Any
        if not d:
            return None
        return dataclass_from_dict(get_args(klass)[0], d)
    elif is_type_Tuple(klass):
        # Type is tuple, can have multiple different types inside
        i = 0
        klass_properties = []
        for item in d:
            klass_properties.append(
                dataclass_from_dict(klass.__args__[i], item))
            i = i + 1
        return tuple(klass_properties)
    elif dataclasses.is_dataclass(klass):
        # Type is a dataclass, data is a dictionary
        fieldtypes = {f.name: f.type for f in dataclasses.fields(klass)}
        return klass(
            **{f: dataclass_from_dict(fieldtypes[f], d[f])
               for f in d})
    elif is_type_List(klass):
        # Type is a list, data is a list
        return [dataclass_from_dict(get_args(klass)[0], item) for item in d]
    elif issubclass(klass, bytes):
        # Type is bytes, data is a hex string
        return klass(hexstr_to_bytes(d))
    elif klass in unhashable_types:
        # Type is unhashable (bls type), so cast from hex string
        return klass.from_bytes(hexstr_to_bytes(d))
    else:
        # Type is a primitive, cast with correct class
        return klass(d)
Пример #16
0
    async def get_network_space(self, request: Dict) -> Optional[Dict]:
        """
        Retrieves an estimate of total space validating the chain
        between two block header hashes.
        """
        if "newer_block_header_hash" not in request or "older_block_header_hash" not in request:
            raise ValueError(
                "Invalid request. newer_block_header_hash and older_block_header_hash required"
            )
        newer_block_hex = request["newer_block_header_hash"]
        older_block_hex = request["older_block_header_hash"]

        if newer_block_hex == older_block_hex:
            raise ValueError("New and old must not be the same")

        newer_block_bytes = hexstr_to_bytes(newer_block_hex)
        older_block_bytes = hexstr_to_bytes(older_block_hex)

        newer_block = await self.service.block_store.get_block_record(
            newer_block_bytes)
        if newer_block is None:
            raise ValueError("Newer block not found")
        older_block = await self.service.block_store.get_block_record(
            older_block_bytes)
        if older_block is None:
            raise ValueError("Newer block not found")
        delta_weight = newer_block.weight - older_block.weight

        delta_iters = newer_block.total_iters - older_block.total_iters
        weight_div_iters = delta_weight / delta_iters
        additional_difficulty_constant = self.service.constants.DIFFICULTY_CONSTANT_FACTOR
        eligible_plots_filter_multiplier = 2**self.service.constants.NUMBER_ZERO_BITS_PLOT_FILTER
        network_space_bytes_estimate = (UI_ACTUAL_SPACE_CONSTANT_FACTOR *
                                        weight_div_iters *
                                        additional_difficulty_constant *
                                        eligible_plots_filter_multiplier)
        return {"space": uint128(int(network_space_bytes_estimate))}
Пример #17
0
async def join_pool(args: dict, wallet_client: WalletRpcClient,
                    fingerprint: int) -> None:
    config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
    enforce_https = config["full_node"]["selected_network"] == "mainnet"
    pool_url: str = args["pool_url"]
    fee = Decimal(args.get("fee", 0))
    fee_mojos = uint64(int(fee * units["chia"]))

    if enforce_https and not pool_url.startswith("https://"):
        print(f"Pool URLs must be HTTPS on mainnet {pool_url}. Aborting.")
        return
    wallet_id = args.get("id", None)
    prompt = not args.get("yes", False)
    try:
        async with aiohttp.ClientSession() as session:
            async with session.get(f"{pool_url}/pool_info",
                                   ssl=ssl_context_for_root(
                                       get_mozilla_ca_crt())) as response:
                if response.ok:
                    json_dict = json.loads(await response.text())
                else:
                    print(f"Response not OK: {response.status}")
                    return
    except Exception as e:
        print(f"Error connecting to pool {pool_url}: {e}")
        return

    if json_dict["relative_lock_height"] > 1000:
        print("Relative lock height too high for this pool, cannot join")
        return
    if json_dict["protocol_version"] != POOL_PROTOCOL_VERSION:
        print(
            f"Incorrect version: {json_dict['protocol_version']}, should be {POOL_PROTOCOL_VERSION}"
        )
        return

    pprint(json_dict)
    msg = f"\nWill join pool: {pool_url} with Plot NFT {fingerprint}."
    func = functools.partial(
        wallet_client.pw_join_pool,
        wallet_id,
        hexstr_to_bytes(json_dict["target_puzzle_hash"]),
        pool_url,
        json_dict["relative_lock_height"],
        fee_mojos,
    )

    await submit_tx_with_confirmation(msg, prompt, func, wallet_client,
                                      fingerprint, wallet_id)
Пример #18
0
def load_pool_config(root_path: Path) -> List[PoolWalletConfig]:
    config = load_config(root_path, "config.yaml")
    ret_list: List[PoolWalletConfig] = []
    if "pool_list" in config["pool"]:
        for pool_config_dict in config["pool"]["pool_list"]:
            try:
                pool_config = PoolWalletConfig(
                    hexstr_to_bytes(pool_config_dict["launcher_id"]),
                    pool_config_dict["pool_url"],
                    pool_config_dict["payout_instructions"],
                    hexstr_to_bytes(pool_config_dict["target_puzzle_hash"]),
                    hexstr_to_bytes(
                        pool_config_dict["p2_singleton_puzzle_hash"]),
                    G1Element.from_bytes(
                        hexstr_to_bytes(pool_config_dict["owner_public_key"])),
                    G1Element.from_bytes(
                        hexstr_to_bytes(
                            pool_config_dict["authentication_public_key"])),
                )
                ret_list.append(pool_config)
            except Exception as e:
                log.error(f"Exception loading config: {pool_config_dict} {e}")

    return ret_list
Пример #19
0
    async def did_recovery_spend(self, request):
        wallet_id = int(request["wallet_id"])
        wallet: DIDWallet = self.service.wallet_state_manager.wallets[
            wallet_id]
        if len(request["attest_filenames"]
               ) < wallet.did_info.num_of_backup_ids_needed:
            return {"success": False, "reason": "insufficient messages"}

        async with self.service.wallet_state_manager.lock:
            (
                info_list,
                message_spend_bundle,
            ) = await wallet.load_attest_files_for_recovery_spend(
                request["attest_filenames"])

            if "pubkey" in request:
                pubkey = G1Element.from_bytes(
                    hexstr_to_bytes(request["pubkey"]))
            else:
                assert wallet.did_info.temp_pubkey is not None
                pubkey = wallet.did_info.temp_pubkey

            if "puzhash" in request:
                puzhash = hexstr_to_bytes(request["puzhash"])
            else:
                assert wallet.did_info.temp_puzhash is not None
                puzhash = wallet.did_info.temp_puzhash

            success = await wallet.recovery_spend(
                wallet.did_info.temp_coin,
                puzhash,
                info_list,
                pubkey,
                message_spend_bundle,
            )
        return {"success": success}
Пример #20
0
    async def get_additions_and_removals(self, request: Dict) -> Optional[Dict]:
        if "header_hash" not in request:
            raise ValueError("No header_hash in request")
        header_hash = hexstr_to_bytes(request["header_hash"])

        block: Optional[FullBlock] = await self.service.block_store.get_full_block(header_hash)
        if block is None:
            raise ValueError(f"Block {header_hash.hex()} not found")

        async with self.service.blockchain.lock:
            if self.service.blockchain.height_to_hash(block.height) != header_hash:
                raise ValueError(f"Block at {header_hash.hex()} is no longer in the blockchain (it's in a fork)")
            additions: List[CoinRecord] = await self.service.coin_store.get_coins_added_at_height(block.height)
            removals: List[CoinRecord] = await self.service.coin_store.get_coins_removed_at_height(block.height)

        return {"additions": additions, "removals": removals}
Пример #21
0
    def replace_str_to_bytes(self, **changes) -> "ConsensusConstants":
        """
        Overrides str (hex) values with bytes.
        """

        filtered_changes = {}
        for k, v in changes.items():
            if not hasattr(self, k):
                log.warn(f'invalid key in network configuration (config.yaml) "{k}". Ignoring')
                continue
            if isinstance(v, str):
                filtered_changes[k] = hexstr_to_bytes(v)
            else:
                filtered_changes[k] = v

        return dataclasses.replace(self, **filtered_changes)
Пример #22
0
    async def create(
        wallet_state_manager: Any,
        wallet: Wallet,
        wallet_info: WalletInfo,
    ) -> CATWallet:
        self = CATWallet()

        self.log = logging.getLogger(__name__)

        self.cost_of_single_tx = None
        self.wallet_state_manager = wallet_state_manager
        self.wallet_info = wallet_info
        self.standard_wallet = wallet
        self.cat_info = CATInfo.from_bytes(
            hexstr_to_bytes(self.wallet_info.data))
        return self
Пример #23
0
 async def did_update_recovery_ids(self, request):
     wallet_id = int(request["wallet_id"])
     wallet: DIDWallet = self.service.wallet_state_manager.wallets[wallet_id]
     recovery_list = []
     for _ in request["new_list"]:
         recovery_list.append(hexstr_to_bytes(_))
     if "num_verifications_required" in request:
         new_amount_verifications_required = uint64(request["num_verifications_required"])
     else:
         new_amount_verifications_required = len(recovery_list)
     success = await wallet.update_recovery_list(recovery_list, new_amount_verifications_required)
     # Update coin with new ID info
     updated_puz = await wallet.get_new_puzzle()
     spend_bundle = await wallet.create_spend(updated_puz.get_tree_hash())
     if spend_bundle is not None and success:
         return {"success": True}
     return {"success": False}
Пример #24
0
    async def create(
        wallet_state_manager: Any,
        wallet: Wallet,
        wallet_info: WalletInfo,
    ) -> CCWallet:
        self = CCWallet()

        self.log = logging.getLogger(__name__)

        self.cost_of_single_tx = None
        self.wallet_state_manager = wallet_state_manager
        self.wallet_info = wallet_info
        self.standard_wallet = wallet
        self.cc_info = CCInfo.from_bytes(hexstr_to_bytes(self.wallet_info.data))
        self.base_puzzle_program = None
        self.base_inner_puzzle_hash = None
        return self
Пример #25
0
 async def puzzle_solution_received(self, response: RespondPuzzleSolution):
     unwrapped: PuzzleSolutionResponse = response.response
     actions: List[WalletAction] = await self.action_store.get_all_pending_actions()
     for action in actions:
         data = json.loads(action.data)
         action_data = data["data"]["action_data"]
         if action.name == "request_puzzle_solution":
             stored_coin_name = bytes32(hexstr_to_bytes(action_data["coin_name"]))
             height = uint32(action_data["height"])
             if stored_coin_name == unwrapped.coin_name and height == unwrapped.height:
                 if action.done:
                     return None
                 wallet = self.wallets[uint32(action.wallet_id)]
                 callback_str = action.wallet_callback
                 if callback_str is not None:
                     callback = getattr(wallet, callback_str)
                     await callback(unwrapped, action.id)
Пример #26
0
    async def generator_received(self, height: uint32, header_hash: uint32, program: Program):

        actions: List[WalletAction] = await self.action_store.get_all_pending_actions()
        for action in actions:
            data = json.loads(action.data)
            action_data = data["data"]["action_data"]
            if action.name == "request_generator":
                stored_header_hash = bytes32(hexstr_to_bytes(action_data["header_hash"]))
                stored_height = uint32(action_data["height"])
                if stored_header_hash == header_hash and stored_height == height:
                    if action.done:
                        return None
                    wallet = self.wallets[uint32(action.wallet_id)]
                    callback_str = action.wallet_callback
                    if callback_str is not None:
                        callback = getattr(wallet, callback_str)
                        await callback(height, header_hash, program, action.id)
Пример #27
0
    async def set_payout_instructions(self, launcher_id: bytes32, payout_instructions: str):
        for p2_singleton_puzzle_hash, pool_state_dict in self.pool_state.items():
            if launcher_id == pool_state_dict["pool_config"].launcher_id:
                config = load_config(self._root_path, "config.yaml")
                new_list = []
                for list_element in config["pool"]["pool_list"]:
                    if hexstr_to_bytes(list_element["launcher_id"]) == bytes(launcher_id):
                        list_element["payout_instructions"] = payout_instructions
                    new_list.append(list_element)

                config["pool"]["pool_list"] = new_list
                save_config(self._root_path, "config.yaml", config)
                # Force a GET /farmer which triggers the PUT /farmer if it detects the changed instructions
                pool_state_dict["next_farmer_update"] = 0
                return

        self.log.warning(f"Launcher id: {launcher_id} not found")
Пример #28
0
    async def _action_messages(self) -> List[Message]:
        if self.wallet_state_manager is None or self.backup_initialized is False:
            return []
        actions: List[WalletAction] = await self.wallet_state_manager.action_store.get_all_pending_actions()
        result: List[Message] = []
        for action in actions:
            data = json.loads(action.data)
            action_data = data["data"]["action_data"]
            if action.name == "request_puzzle_solution":
                coin_name = bytes32(hexstr_to_bytes(action_data["coin_name"]))
                height = uint32(action_data["height"])
                msg = make_msg(
                    ProtocolMessageTypes.request_puzzle_solution,
                    wallet_protocol.RequestPuzzleSolution(coin_name, height),
                )
                result.append(msg)

        return result
Пример #29
0
    async def get_coin_records_by_puzzle_hash(self, request: Dict) -> Optional[Dict]:
        """
        Retrieves the coins for a given puzzlehash, by default returns unspent coins.
        """
        if "puzzle_hash" not in request:
            raise ValueError("Puzzle hash not in request")
        kwargs: Dict[str, Any] = {"include_spent_coins": False, "puzzle_hash": hexstr_to_bytes(request["puzzle_hash"])}
        if "start_height" in request:
            kwargs["start_height"] = uint32(request["start_height"])
        if "end_height" in request:
            kwargs["end_height"] = uint32(request["end_height"])

        if "include_spent_coins" in request:
            kwargs["include_spent_coins"] = request["include_spent_coins"]

        coin_records = await self.service.blockchain.coin_store.get_coin_records_by_puzzle_hash(**kwargs)

        return {"coin_records": coin_records}
Пример #30
0
 async def get_signage_point(self, request: Dict) -> Dict:
     sp_hash = hexstr_to_bytes(request["sp_hash"])
     for _, sps in self.service.sps.items():
         for sp in sps:
             if sp.challenge_chain_sp == sp_hash:
                 pospaces = self.service.proofs_of_space.get(sp.challenge_chain_sp, [])
                 return {
                     "signage_point": {
                         "challenge_hash": sp.challenge_hash,
                         "challenge_chain_sp": sp.challenge_chain_sp,
                         "reward_chain_sp": sp.reward_chain_sp,
                         "difficulty": sp.difficulty,
                         "sub_slot_iters": sp.sub_slot_iters,
                         "signage_point_index": sp.signage_point_index,
                     },
                     "proofs": pospaces,
                 }
     raise ValueError(f"Signage point {sp_hash.hex()} not found")