Ejemplo n.º 1
0
    async def start(self):
        self.store = await PoolStore.create()
        self.pending_point_partials = asyncio.Queue()

        self_hostname = self.config["self_hostname"]
        self.node_rpc_client = await FullNodeRpcClient.create(
            self_hostname, uint16(8555), DEFAULT_ROOT_PATH, self.config)
        self.wallet_rpc_client = await WalletRpcClient.create(
            self.config["self_hostname"], uint16(9256), DEFAULT_ROOT_PATH,
            self.config)
        self.blockchain_state = await self.node_rpc_client.get_blockchain_state(
        )
        res = await self.wallet_rpc_client.log_in_and_skip(
            fingerprint=self.wallet_fingerprint)
        self.log.info(f"Logging in: {res}")
        res = await self.wallet_rpc_client.get_wallet_balance(self.wallet_id)
        self.log.info(f"Obtaining balance: {res}")

        self.scan_p2_singleton_puzzle_hashes = await self.store.get_pay_to_singleton_phs(
        )

        self.confirm_partials_loop_task = asyncio.create_task(
            self.confirm_partials_loop())
        self.collect_pool_rewards_loop_task = asyncio.create_task(
            self.collect_pool_rewards_loop())
        self.create_payment_loop_task = asyncio.create_task(
            self.create_payment_loop())
        self.submit_payment_loop_task = asyncio.create_task(
            self.submit_payment_loop())
        self.get_peak_loop_task = asyncio.create_task(self.get_peak_loop())

        self.pending_payments = asyncio.Queue()
def _run_generator(
    constants_dict: bytes,
    unfinished_block_bytes: bytes,
    block_generator_bytes: bytes,
    height: uint32,
) -> Optional[bytes]:
    """
    Runs the CLVM generator from bytes inputs. This is meant to be called under a ProcessPoolExecutor, in order to
    validate the heavy parts of a block (clvm program) in a different process.
    """
    try:
        constants: ConsensusConstants = dataclass_from_dict(
            ConsensusConstants, constants_dict)
        unfinished_block: UnfinishedBlock = UnfinishedBlock.from_bytes(
            unfinished_block_bytes)
        assert unfinished_block.transactions_info is not None
        block_generator: BlockGenerator = BlockGenerator.from_bytes(
            block_generator_bytes)
        assert block_generator.program == unfinished_block.transactions_generator
        npc_result: NPCResult = get_name_puzzle_conditions(
            block_generator,
            min(constants.MAX_BLOCK_COST_CLVM,
                unfinished_block.transactions_info.cost),
            cost_per_byte=constants.COST_PER_BYTE,
            mempool_mode=False,
            height=height,
        )
        return bytes(npc_result)
    except ValidationError as e:
        return bytes(NPCResult(uint16(e.code.value), [], uint64(0)))
    except Exception:
        return bytes(NPCResult(uint16(Err.UNKNOWN.value), [], uint64(0)))
def get_name_puzzle_conditions_rust(generator: BlockGenerator, max_cost: int,
                                    *, cost_per_byte: int,
                                    safe_mode: bool) -> NPCResult:
    block_program, block_program_args = setup_generator_args(generator)
    max_cost -= len(bytes(generator.program)) * cost_per_byte
    if max_cost < 0:
        return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0))

    flags = STRICT_MODE if safe_mode else 0
    err, result, clvm_cost = GENERATOR_MOD.run_as_generator(
        max_cost, flags, block_program, block_program_args)
    if err is not None:
        return NPCResult(uint16(err), [], uint64(0))
    else:
        npc_list = []
        for r in result:
            conditions = []
            for c in r.conditions:
                cwa = []
                for cond_list in c[1]:
                    cwa.append(
                        ConditionWithArgs(
                            ConditionOpcode(bytes([cond_list.opcode])),
                            cond_list.vars))
                conditions.append((ConditionOpcode(bytes([c[0]])), cwa))
            npc_list.append(NPC(r.coin_name, r.puzzle_hash, conditions))
        return NPCResult(None, npc_list, uint64(clvm_cost))
def get_name_puzzle_conditions(generator: BlockGenerator, max_cost: int, *,
                               cost_per_byte: int, safe_mode: bool,
                               rust_checker: bool) -> NPCResult:
    """
    This executes the generator program and returns the coins and their
    conditions. If the cost of the program (size, CLVM execution and conditions)
    exceed max_cost, the function fails. In order to accurately take the size
    of the program into account when calculating cost, cost_per_byte must be
    specified.
    safe_mode determines whether the clvm program and conditions are executed in
    strict mode or not. When in safe/strict mode, unknow operations or conditions
    are considered failures. This is the mode when accepting transactions into
    the mempool.
    """
    try:
        if rust_checker:
            return get_name_puzzle_conditions_rust(generator,
                                                   max_cost,
                                                   cost_per_byte=cost_per_byte,
                                                   safe_mode=safe_mode)
        else:
            return get_name_puzzle_conditions_python(
                generator,
                max_cost,
                cost_per_byte=cost_per_byte,
                safe_mode=safe_mode)
    except ValidationError as e:
        return NPCResult(uint16(e.code.value), [], uint64(0))
    except Exception as e:
        log.debug(f"get_name_puzzle_condition failed: {e}")
        return NPCResult(uint16(Err.GENERATOR_RUNTIME_ERROR.value), [],
                         uint64(0))
Ejemplo n.º 5
0
    async def start(self):
        self.store = await PoolStore.create()
        self.pending_point_partials = asyncio.Queue()

        print(self.config)
        self_hostname = self.config["self_hostname"]
        self.node_rpc_client = await FullNodeRpcClient.create(
            self_hostname, uint16(8555), DEFAULT_ROOT_PATH, self.config)
        self.wallet_rpc_client = await WalletRpcClient.create(
            self.config["self_hostname"], uint16(9256), DEFAULT_ROOT_PATH,
            self.config)
        await self.wallet_rpc_client.get_wallet_balance(self.wallet_id)
        self.scan_p2_singleton_puzzle_hashes = await self.store.get_pay_to_singleton_phs(
        )

        self.confirm_partials_loop_task = asyncio.create_task(
            self.confirm_partials_loop())
        self.collect_pool_rewards_loop_task = asyncio.create_task(
            self.collect_pool_rewards_loop())
        self.create_payment_loop_task = asyncio.create_task(
            self.create_payment_loop())
        self.submit_payment_loop_task = asyncio.create_task(
            self.submit_payment_loop())

        self.pending_payments = asyncio.Queue()
Ejemplo n.º 6
0
 def from_string(cls, peer_str: str):
     blobs = peer_str.split(" ")
     assert len(blobs) == 5
     peer_info = TimestampedPeerInfo(blobs[0], uint16(int(blobs[1])),
                                     uint64(int(blobs[2])))
     src_peer = PeerInfo(blobs[3], uint16(int(blobs[4])))
     return cls(peer_info, src_peer)
Ejemplo n.º 7
0
async def wallets_prefarm(two_wallet_nodes):
    """
    Sets up the node with 10 blocks, and returns a payer and payee wallet.
    """
    farm_blocks = 10
    buffer = 4
    full_nodes, wallets = two_wallet_nodes
    full_node_api = full_nodes[0]
    full_node_server = full_node_api.server
    wallet_node_0, wallet_server_0 = wallets[0]
    wallet_node_1, wallet_server_1 = wallets[1]
    wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
    wallet_1 = wallet_node_1.wallet_state_manager.main_wallet

    ph0 = await wallet_0.get_new_puzzlehash()
    ph1 = await wallet_1.get_new_puzzlehash()

    await wallet_server_0.start_client(
        PeerInfo("localhost", uint16(full_node_server._port)), None)
    await wallet_server_1.start_client(
        PeerInfo("localhost", uint16(full_node_server._port)), None)

    for i in range(0, farm_blocks):
        await full_node_api.farm_new_transaction_block(
            FarmNewBlockProtocol(ph0))

    for i in range(0, farm_blocks):
        await full_node_api.farm_new_transaction_block(
            FarmNewBlockProtocol(ph1))

    for i in range(0, buffer):
        await full_node_api.farm_new_transaction_block(
            FarmNewBlockProtocol(token_bytes()))

    return wallet_node_0, wallet_node_1, full_node_api
Ejemplo n.º 8
0
def get_name_puzzle_conditions(
    generator: BlockGenerator, max_cost: int, *, cost_per_byte: int, mempool_mode: bool
) -> NPCResult:
    block_program, block_program_args = setup_generator_args(generator)
    max_cost -= len(bytes(generator.program)) * cost_per_byte
    if max_cost < 0:
        return NPCResult(uint16(Err.INVALID_BLOCK_COST.value), [], uint64(0))

    flags = MEMPOOL_MODE if mempool_mode else 0
    try:
        err, result, clvm_cost = GENERATOR_MOD.run_as_generator(max_cost, flags, block_program, block_program_args)
        if err is not None:
            return NPCResult(uint16(err), [], uint64(0))
        else:
            npc_list = []
            for r in result:
                conditions = []
                for c in r.conditions:
                    cwa = []
                    for cond_list in c[1]:
                        cwa.append(ConditionWithArgs(ConditionOpcode(bytes([cond_list.opcode])), cond_list.vars))
                    conditions.append((ConditionOpcode(bytes([c[0]])), cwa))
                npc_list.append(NPC(r.coin_name, r.puzzle_hash, conditions))
            return NPCResult(None, npc_list, uint64(clvm_cost))
    except BaseException as e:
        log.debug(f"get_name_puzzle_condition failed: {e}")
        return NPCResult(uint16(Err.GENERATOR_RUNTIME_ERROR.value), [], uint64(0))
Ejemplo n.º 9
0
    async def perform_handshake(self, network_id: str, protocol_version: str, server_port: int, local_type: NodeType):
        if self.is_outbound:
            outbound_handshake = make_msg(
                ProtocolMessageTypes.handshake,
                Handshake(
                    network_id,
                    protocol_version,
                    chia_full_version_str(),
                    uint16(server_port),
                    uint8(local_type.value),
                    [(uint16(Capability.BASE.value), "1")],
                ),
            )
            assert outbound_handshake is not None
            await self._send_message(outbound_handshake)
            inbound_handshake_msg = await self._read_one_message()
            if inbound_handshake_msg is None:
                raise ProtocolError(Err.INVALID_HANDSHAKE)
            inbound_handshake = Handshake.from_bytes(inbound_handshake_msg.data)
            if ProtocolMessageTypes(inbound_handshake_msg.type) != ProtocolMessageTypes.handshake:
                raise ProtocolError(Err.INVALID_HANDSHAKE)
            if inbound_handshake.network_id != network_id:
                raise ProtocolError(Err.INCOMPATIBLE_NETWORK_ID)

            self.peer_server_port = inbound_handshake.server_port
            self.connection_type = NodeType(inbound_handshake.node_type)

        else:
            try:
                message = await self._read_one_message()
            except Exception:
                raise ProtocolError(Err.INVALID_HANDSHAKE)

            if message is None:
                raise ProtocolError(Err.INVALID_HANDSHAKE)
            inbound_handshake = Handshake.from_bytes(message.data)
            if ProtocolMessageTypes(message.type) != ProtocolMessageTypes.handshake:
                raise ProtocolError(Err.INVALID_HANDSHAKE)
            if inbound_handshake.network_id != network_id:
                raise ProtocolError(Err.INCOMPATIBLE_NETWORK_ID)
            outbound_handshake = make_msg(
                ProtocolMessageTypes.handshake,
                Handshake(
                    network_id,
                    protocol_version,
                    chia_full_version_str(),
                    uint16(server_port),
                    uint8(local_type.value),
                    [(uint16(Capability.BASE.value), "1")],
                ),
            )
            await self._send_message(outbound_handshake)
            self.peer_server_port = inbound_handshake.server_port
            self.connection_type = NodeType(inbound_handshake.node_type)

        self.outbound_task = asyncio.create_task(self.outbound_handler())
        self.inbound_task = asyncio.create_task(self.inbound_handler())
        return True
Ejemplo n.º 10
0
    async def test_generate_zero_val(self, two_wallet_nodes):
        num_blocks = 4
        full_nodes, wallets = two_wallet_nodes
        full_node_api = full_nodes[0]
        full_node_server = full_node_api.server
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet
        wallet2 = wallet_node_2.wallet_state_manager.main_wallet

        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None)
        await server_3.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None)
        for i in range(1, num_blocks):
            await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))

        funds = sum(
            [
                calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i))
                for i in range(1, num_blocks - 1)
            ]
        )
        await time_out_assert(15, wallet.get_confirmed_balance, funds)

        cc_wallet: CCWallet = await CCWallet.create_new_cc(wallet_node.wallet_state_manager, wallet, uint64(100))

        ph = await wallet2.get_new_puzzlehash()
        for i in range(1, num_blocks):
            await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))

        await time_out_assert(15, cc_wallet.get_confirmed_balance, 100)
        await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)

        assert cc_wallet.cc_info.my_genesis_checker is not None
        colour = cc_wallet.get_colour()

        cc_wallet_2: CCWallet = await CCWallet.create_wallet_for_cc(wallet_node_2.wallet_state_manager, wallet2, colour)

        assert cc_wallet.cc_info.my_genesis_checker == cc_wallet_2.cc_info.my_genesis_checker

        spend_bundle = await cc_wallet_2.generate_zero_val_coin()
        await time_out_assert(15, tx_in_pool, True, full_node_api.full_node.mempool_manager, spend_bundle.name())
        for i in range(1, num_blocks):
            await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))

        async def unspent_count():
            unspent: List[WalletCoinRecord] = list(
                await cc_wallet_2.wallet_state_manager.get_spendable_coins_for_wallet(cc_wallet_2.id())
            )
            return len(unspent)

        await time_out_assert(15, unspent_count, 1)
        unspent: List[WalletCoinRecord] = list(
            await cc_wallet_2.wallet_state_manager.get_spendable_coins_for_wallet(cc_wallet_2.id())
        )
        assert unspent.pop().coin.amount == 0
Ejemplo n.º 11
0
    async def validate_unfinished_block(
        self, block: UnfinishedBlock, skip_overflow_ss_validation=True
    ) -> PreValidationResult:
        if (
            not self.contains_block(block.prev_header_hash)
            and not block.prev_header_hash == self.constants.GENESIS_CHALLENGE
        ):
            return PreValidationResult(uint16(Err.INVALID_PREV_BLOCK_HASH.value), None, None)

        unfinished_header_block = UnfinishedHeaderBlock(
            block.finished_sub_slots,
            block.reward_chain_block,
            block.challenge_chain_sp_proof,
            block.reward_chain_sp_proof,
            block.foliage,
            block.foliage_transaction_block,
            b"",
        )
        prev_b = self.try_block_record(unfinished_header_block.prev_header_hash)
        sub_slot_iters, difficulty = get_next_sub_slot_iters_and_difficulty(
            self.constants, len(unfinished_header_block.finished_sub_slots) > 0, prev_b, self
        )
        required_iters, error = validate_unfinished_header_block(
            self.constants,
            self,
            unfinished_header_block,
            False,
            difficulty,
            sub_slot_iters,
            skip_overflow_ss_validation,
        )

        if error is not None:
            return PreValidationResult(uint16(error.code.value), None, None)

        prev_height = (
            -1
            if block.prev_header_hash == self.constants.GENESIS_CHALLENGE
            else self.block_record(block.prev_header_hash).height
        )

        error_code, cost_result = await validate_block_body(
            self.constants,
            self,
            self.block_store,
            self.coin_store,
            self.get_peak(),
            block,
            uint32(prev_height + 1),
            None,
        )

        if error_code is not None:
            return PreValidationResult(uint16(error_code.value), None, None)

        return PreValidationResult(None, required_iters, cost_result)
Ejemplo n.º 12
0
async def environment(simulation):
    harvester_service, farmer_service = simulation

    def stop_node_cb():
        pass

    config = bt.config
    hostname = config["self_hostname"]
    daemon_port = config["daemon_port"]

    farmer_rpc_api = FarmerRpcApi(farmer_service._api.farmer)
    harvester_rpc_api = HarvesterRpcApi(harvester_service._node)

    rpc_port_farmer = uint16(21522)
    rpc_port_harvester = uint16(21523)

    rpc_cleanup = await start_rpc_server(
        farmer_rpc_api,
        hostname,
        daemon_port,
        rpc_port_farmer,
        stop_node_cb,
        bt.root_path,
        config,
        connect_to_daemon=False,
    )
    rpc_cleanup_2 = await start_rpc_server(
        harvester_rpc_api,
        hostname,
        daemon_port,
        rpc_port_harvester,
        stop_node_cb,
        bt.root_path,
        config,
        connect_to_daemon=False,
    )

    farmer_rpc_client = await FarmerRpcClient.create(self_hostname,
                                                     rpc_port_farmer,
                                                     bt.root_path, config)
    harvester_rpc_client = await HarvesterRpcClient.create(
        self_hostname, rpc_port_harvester, bt.root_path, config)

    async def have_connections():
        return len(await farmer_rpc_client.get_connections()) > 0

    await time_out_assert(15, have_connections, True)

    yield farmer_service, farmer_rpc_api, farmer_rpc_client, harvester_service, harvester_rpc_api, harvester_rpc_client

    farmer_rpc_client.close()
    harvester_rpc_client.close()
    await farmer_rpc_client.await_closed()
    await harvester_rpc_client.await_closed()
    await rpc_cleanup()
    await rpc_cleanup_2()
Ejemplo n.º 13
0
    async def test_simulation_1(self, simulation, extra_node):
        node1, node2, _, _, _, _, _, _, _, sanitizer_server, server1 = simulation
        await server1.start_client(PeerInfo(self_hostname, uint16(21238)))
        # Use node2 to test node communication, since only node1 extends the chain.
        await time_out_assert(1500, node_height_at_least, True, node2, 7)
        await sanitizer_server.start_client(
            PeerInfo(self_hostname, uint16(21238)))

        async def has_compact(node1, node2):
            peak_height_1 = node1.full_node.blockchain.get_peak_height()
            headers_1 = await node1.full_node.blockchain.get_header_blocks_in_range(
                0, peak_height_1 - 6)
            peak_height_2 = node2.full_node.blockchain.get_peak_height()
            headers_2 = await node2.full_node.blockchain.get_header_blocks_in_range(
                0, peak_height_2 - 6)
            # Commented to speed up.
            # cc_eos = [False, False]
            # icc_eos = [False, False]
            # cc_sp = [False, False]
            # cc_ip = [False, False]
            has_compact = [False, False]
            for index, headers in enumerate([headers_1, headers_2]):
                for header in headers.values():
                    for sub_slot in header.finished_sub_slots:
                        if sub_slot.proofs.challenge_chain_slot_proof.normalized_to_identity:
                            # cc_eos[index] = True
                            has_compact[index] = True
                        if (sub_slot.proofs.infused_challenge_chain_slot_proof
                                is not None and sub_slot.proofs.
                                infused_challenge_chain_slot_proof.
                                normalized_to_identity):
                            # icc_eos[index] = True
                            has_compact[index] = True
                    if (header.challenge_chain_sp_proof is not None and header.
                            challenge_chain_sp_proof.normalized_to_identity):
                        # cc_sp[index] = True
                        has_compact[index] = True
                    if header.challenge_chain_ip_proof.normalized_to_identity:
                        # cc_ip[index] = True
                        has_compact[index] = True

            # return (
            #     cc_eos == [True, True] and icc_eos == [True, True] and cc_sp == [True, True] and cc_ip == [True, True]
            # )
            return has_compact == [True, True]

        await time_out_assert(1500, has_compact, True, node1, node2)
        node3 = extra_node
        server3 = node3.full_node.server
        peak_height = max(node1.full_node.blockchain.get_peak_height(),
                          node2.full_node.blockchain.get_peak_height())
        await server3.start_client(PeerInfo(self_hostname, uint16(21237)))
        await server3.start_client(PeerInfo(self_hostname, uint16(21238)))
        await time_out_assert(600, node_height_at_least, True, node3,
                              peak_height)
Ejemplo n.º 14
0
async def check_node_alive(node: Node) -> Tuple[bool, Node]:
    ssl_context = ssl_context_for_server('keys/chia_ca.crt',
                                         'keys/chia_ca.key',
                                         'keys/public_full_node.crt',
                                         'keys/public_full_node.key')
    try:
        # TODO: connect and timeout in one shot, don't do it in two connections
        await asyncio.wait_for(websockets.connect(node.get_websocket_url(),
                                                  ssl=ssl_context),
                               timeout=10)
        async with websockets.connect(node.get_websocket_url(),
                                      ssl=ssl_context) as websocket:
            handshake = make_msg(
                ProtocolMessageTypes.handshake,
                Handshake(
                    'mainnet',
                    protocol_version,
                    '0.0.0',
                    uint16(8884),
                    uint8(NodeType.INTRODUCER),
                    [(uint16(Capability.BASE.value), '1')],
                ))
            encoded_handshake = bytes(handshake)
            await websocket.send(encoded_handshake)
            message = await websocket.recv()

            if message is None:
                logging.warning('Node ' + node.ip + ' did not return anything')
                return False, node
            full_message_loaded = Message.from_bytes(message)
            inbound_handshake = Handshake.from_bytes(full_message_loaded.data)
            await websocket.close()

            if inbound_handshake.network_id != 'mainnet':
                logging.warning('Node ' + node.ip +
                                ' is not on main net but is on mainnet port!')
                return False, node

            logging.info('Node ' + node.ip + ' is up.')
            return True, node
    except websockets.exceptions.ConnectionClosed as e:
        logging.warning('Node closed the connection')
        return False, node
    except asyncio.exceptions.TimeoutError as e:
        logging.warning('Node timeout : ' + node.ip)
        return False, node
    except websockets.exceptions.InvalidMessage as e:
        return False, node
    except OSError as e:
        return False, node
    except Exception as e:
        logging.error(e)
        traceback.print_exc()
        return False, node
Ejemplo n.º 15
0
    async def test_sync_bad_peak_while_synced(self, three_nodes,
                                              default_1000_blocks,
                                              default_10000_blocks):
        # Must be larger than "sync_block_behind_threshold" in the config
        num_blocks_initial = len(default_1000_blocks) - 250
        blocks_750 = default_1000_blocks[:num_blocks_initial]
        full_node_1, full_node_2, full_node_3 = three_nodes
        server_1 = full_node_1.full_node.server
        server_2 = full_node_2.full_node.server
        server_3 = full_node_3.full_node.server
        full_node_3.full_node.weight_proof_handler = None
        for block in blocks_750:
            await full_node_1.full_node.respond_block(
                full_node_protocol.RespondBlock(block))
        # Node 3 syncs from a different blockchain

        for block in default_10000_blocks[:1100]:
            await full_node_3.full_node.respond_block(
                full_node_protocol.RespondBlock(block))

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(server_1._port)),
            full_node_2.full_node.on_connect)

        # The second node should eventually catch up to the first one, and have the
        # same tip at height num_blocks - 1
        await time_out_assert(180, node_height_exactly, True, full_node_2,
                              num_blocks_initial - 1)
        # set new heavy peak, fn3 cannot serve wp's
        # node 2 should keep being synced and receive blocks
        await server_3.start_client(
            PeerInfo(self_hostname, uint16(server_3._port)),
            full_node_3.full_node.on_connect)
        # trigger long sync in full node 2
        peak_block = default_10000_blocks[1050]
        await server_2.start_client(
            PeerInfo(self_hostname, uint16(server_3._port)),
            full_node_2.full_node.on_connect)
        con = server_2.all_connections[full_node_3.full_node.server.node_id]
        peak = full_node_protocol.NewPeak(
            peak_block.header_hash,
            peak_block.height,
            peak_block.weight,
            peak_block.height,
            peak_block.reward_chain_block.get_unfinished().get_hash(),
        )
        await full_node_2.full_node.new_peak(peak, con)
        await asyncio.sleep(2)
        assert not full_node_2.full_node.sync_store.get_sync_mode()
        for block in default_1000_blocks[1000 - num_blocks_initial:]:
            await full_node_2.full_node.respond_block(
                full_node_protocol.RespondBlock(block))

        assert node_height_exactly(full_node_2, 999)
Ejemplo n.º 16
0
    async def create_request(self, message_no_id: Message,
                             timeout: int) -> Optional[Message]:
        """Sends a message and waits for a response."""
        if self.closed:
            return None

        # We will wait for this event, it will be set either by the response, or the timeout
        event = asyncio.Event()

        # The request nonce is an integer between 0 and 2**16 - 1, which is used to match requests to responses
        # If is_outbound, 0 <= nonce < 2^15, else  2^15 <= nonce < 2^16
        request_id = self.request_nonce
        if self.is_outbound:
            self.request_nonce = uint16(self.request_nonce +
                                        1) if self.request_nonce != (
                                            2**15 - 1) else uint16(0)
        else:
            self.request_nonce = (uint16(self.request_nonce +
                                         1) if self.request_nonce !=
                                  (2**16 - 1) else uint16(2**15))

        message = Message(message_no_id.type, request_id, message_no_id.data)

        self.pending_requests[message.id] = event
        await self.outgoing_queue.put(message)

        # If the timeout passes, we set the event
        async def time_out(req_id, req_timeout):
            try:
                await asyncio.sleep(req_timeout)
                if req_id in self.pending_requests:
                    self.pending_requests[req_id].set()
            except asyncio.CancelledError:
                if req_id in self.pending_requests:
                    self.pending_requests[req_id].set()
                raise

        timeout_task = asyncio.create_task(time_out(message.id, timeout))
        self.pending_timeouts[message.id] = timeout_task
        await event.wait()

        self.pending_requests.pop(message.id)
        result: Optional[Message] = None
        if message.id in self.request_results:
            result = self.request_results[message.id]
            assert result is not None
            self.log.debug(
                f"<- {ProtocolMessageTypes(result.type).name} from: {self.peer_host}:{self.peer_port}"
            )
            self.request_results.pop(result.id)

        return result
Ejemplo n.º 17
0
 async def start(self):
     self.store = await PoolStore.create()
     self.pending_point_partials = asyncio.Queue()
     self.full_node_client = await FullNodeRpcClient.create(
         self.config["self_hostname"], uint16(8555), DEFAULT_ROOT_PATH,
         self.config)
     self.confirm_partials_loop_task = asyncio.create_task(
         self.confirm_partials_loop())
     self_hostname = self.config["self_hostname"]
     self.node_rpc_client = await FullNodeRpcClient.create(
         self_hostname, uint16(8555), DEFAULT_ROOT_PATH, self.config)
     self.scan_p2_singleton_puzzle_hashes = await self.store.get_pay_to_singleton_phs(
     )
Ejemplo n.º 18
0
    async def test_wallet_send_to_three_peers(self, three_sim_two_wallets):
        num_blocks = 10
        full_nodes, wallets = three_sim_two_wallets

        wallet_0, wallet_server_0 = wallets[0]
        full_node_api_0 = full_nodes[0]
        full_node_api_1 = full_nodes[1]
        full_node_api_2 = full_nodes[2]

        full_node_0 = full_node_api_0.full_node
        full_node_1 = full_node_api_1.full_node
        full_node_2 = full_node_api_2.full_node

        server_0 = full_node_0.server
        server_1 = full_node_1.server
        server_2 = full_node_2.server

        ph = await wallet_0.wallet_state_manager.main_wallet.get_new_puzzlehash()

        # wallet0 <-> sever0
        await wallet_server_0.start_client(PeerInfo(self_hostname, uint16(server_0._port)), None)

        for i in range(0, num_blocks):
            await full_node_api_0.farm_new_transaction_block(FarmNewBlockProtocol(ph))

        all_blocks = await full_node_api_0.get_all_full_blocks()

        for block in all_blocks:
            await full_node_1.respond_block(RespondBlock(block))
            await full_node_2.respond_block(RespondBlock(block))

        funds = sum(
            [calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks)]
        )

        await time_out_assert(5, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, funds)

        tx = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(10, 32 * b"0", 0)
        await wallet_0.wallet_state_manager.main_wallet.push_transaction(tx)

        await time_out_assert_not_none(5, full_node_0.mempool_manager.get_spendbundle, tx.spend_bundle.name())

        # wallet0 <-> sever1
        await wallet_server_0.start_client(PeerInfo(self_hostname, uint16(server_1._port)), wallet_0.on_connect)

        await time_out_assert_not_none(5, full_node_1.mempool_manager.get_spendbundle, tx.spend_bundle.name())

        # wallet0 <-> sever2
        await wallet_server_0.start_client(PeerInfo(self_hostname, uint16(server_2._port)), wallet_0.on_connect)

        await time_out_assert_not_none(5, full_node_2.mempool_manager.get_spendbundle, tx.spend_bundle.name())
def batch_pre_validate_blocks(
    constants_dict: Dict,
    blocks_pickled: Dict[bytes, bytes],
    header_blocks_pickled: List[bytes],
    transaction_generators: List[Optional[bytes]],
    check_filter: bool,
    expected_difficulty: List[uint64],
    expected_sub_slot_iters: List[uint64],
    validate_transactions: bool,
) -> List[bytes]:
    assert len(header_blocks_pickled) == len(transaction_generators)
    blocks = {}
    for k, v in blocks_pickled.items():
        blocks[k] = BlockRecord.from_bytes(v)
    results: List[PreValidationResult] = []
    constants: ConsensusConstants = dataclass_from_dict(
        ConsensusConstants, constants_dict)
    for i in range(len(header_blocks_pickled)):
        try:
            header_block: HeaderBlock = HeaderBlock.from_bytes(
                header_blocks_pickled[i])
            generator: Optional[bytes] = transaction_generators[i]
            required_iters, error = validate_finished_header_block(
                constants,
                BlockCache(blocks),
                header_block,
                check_filter,
                expected_difficulty[i],
                expected_sub_slot_iters[i],
            )
            cost_result: Optional[CostResult] = None
            error_int: Optional[uint16] = None
            if error is not None:
                error_int = uint16(error.code.value)
            if constants_dict["NETWORK_TYPE"] == NetworkType.MAINNET.value:
                cost_result = None
            else:
                if not error and generator is not None and validate_transactions:
                    cost_result = calculate_cost_of_program(
                        SerializedProgram.from_bytes(generator),
                        constants.CLVM_COST_RATIO_CONSTANT)
            results.append(
                PreValidationResult(error_int, required_iters, cost_result))
        except Exception:
            error_stack = traceback.format_exc()
            log.error(f"Exception: {error_stack}")
            results.append(
                PreValidationResult(uint16(Err.UNKNOWN.value), None, None))
    return [bytes(r) for r in results]
Ejemplo n.º 20
0
    async def test_did_recovery_with_empty_set(self, two_wallet_nodes):
        num_blocks = 5
        full_nodes, wallets = two_wallet_nodes
        full_node_1 = full_nodes[0]
        server_1 = full_node_1.server
        wallet_node, server_2 = wallets[0]
        wallet_node_2, server_3 = wallets[1]
        wallet = wallet_node.wallet_state_manager.main_wallet

        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)
        await server_3.start_client(
            PeerInfo("localhost", uint16(server_1._port)), None)

        for i in range(1, num_blocks):
            await full_node_1.farm_new_transaction_block(
                FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_pool_reward(uint32(i)) +
            calculate_base_farmer_reward(uint32(i))
            for i in range(1, num_blocks - 1)
        ])

        await time_out_assert(15, wallet.get_confirmed_balance, funds)

        async with wallet_node.wallet_state_manager.lock:
            did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
                wallet_node.wallet_state_manager, wallet, uint64(101))

        for i in range(1, num_blocks):
            await full_node_1.farm_new_transaction_block(
                FarmNewBlockProtocol(ph))

        await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
        await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
        coins = await did_wallet.select_coins(1)
        coin = coins.pop()
        info = Program.to([])
        pubkey = (await
                  did_wallet.wallet_state_manager.get_unused_derivation_record(
                      did_wallet.wallet_info.id)).pubkey
        spend_bundle = await did_wallet.recovery_spend(
            coin, ph, info, pubkey, SpendBundle([],
                                                AugSchemeMPL.aggregate([])))
        additions = spend_bundle.additions()
        assert additions == []
Ejemplo n.º 21
0
    async def get_peer_info(self) -> Optional[PeerInfo]:
        ip = None
        port = self._port

        # Use chia's service first.
        try:
            timeout = ClientTimeout(total=15)
            async with ClientSession(timeout=timeout) as session:
                async with session.get("https://ip.chia.net/") as resp:
                    if resp.status == 200:
                        ip = str(await resp.text())
                        ip = ip.rstrip()
        except Exception:
            ip = None

        # Fallback to `checkip` from amazon.
        if ip is None:
            try:
                timeout = ClientTimeout(total=15)
                async with ClientSession(timeout=timeout) as session:
                    async with session.get(
                            "https://checkip.amazonaws.com/") as resp:
                        if resp.status == 200:
                            ip = str(await resp.text())
                            ip = ip.rstrip()
            except Exception:
                ip = None
        if ip is None:
            return None
        peer = PeerInfo(ip, uint16(port))
        if not peer.is_valid():
            return None
        return peer
Ejemplo n.º 22
0
    async def test_blocks_load(self, two_nodes):
        num_blocks = 50
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = bt.get_consecutive_blocks(num_blocks)
        peer = await connect_and_get_peer(server_1, server_2)
        await full_node_1.full_node.respond_block(
            full_node_protocol.RespondBlock(blocks[0]), peer)

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(server_1._port)), None)

        async def num_connections():
            return len(server_2.get_connections())

        await time_out_assert(10, num_connections, 1)

        start_unf = time.time()
        for i in range(1, num_blocks):
            await full_node_1.full_node.respond_block(
                full_node_protocol.RespondBlock(blocks[i]))
            await full_node_2.full_node.respond_block(
                full_node_protocol.RespondBlock(blocks[i]))
        print(
            f"Time taken to process {num_blocks} is {time.time() - start_unf}")
        assert time.time() - start_unf < 100
Ejemplo n.º 23
0
async def execute_with_wallet(wallet_rpc_port: int, fingerprint: int,
                              extra_params: dict, function: Callable) -> None:
    try:
        config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
        self_hostname = config["self_hostname"]
        if wallet_rpc_port is None:
            wallet_rpc_port = config["wallet"]["rpc_port"]
        wallet_client = await WalletRpcClient.create(self_hostname,
                                                     uint16(wallet_rpc_port),
                                                     DEFAULT_ROOT_PATH, config)
        wallet_client_f = await get_wallet(wallet_client,
                                           fingerprint=fingerprint)
        if wallet_client_f is None:
            wallet_client.close()
            await wallet_client.await_closed()
            return
        wallet_client, fingerprint = wallet_client_f
        await function(extra_params, wallet_client, fingerprint)
    except KeyboardInterrupt:
        pass
    except Exception as e:
        if isinstance(e, aiohttp.ClientConnectorError):
            print(
                f"Connection error. Check if wallet is running at {wallet_rpc_port}"
            )
        else:
            print(f"Exception from 'wallet' {e}")
    wallet_client.close()
    await wallet_client.await_closed()
Ejemplo n.º 24
0
async def disconnect_all_and_reconnect(server: ChiaServer,
                                       reconnect_to: ChiaServer) -> bool:
    cons = list(server.all_connections.values())[:]
    for con in cons:
        await con.close()
    return await server.start_client(
        PeerInfo(self_hostname, uint16(reconnect_to._port)), None)
Ejemplo n.º 25
0
    async def test_wallet_coinbase_reorg(self, wallet_node):
        num_blocks = 5
        full_nodes, wallets = wallet_node
        full_node_api = full_nodes[0]
        fn_server = full_node_api.full_node.server
        wallet_node, server_2 = wallets[0]
        wallet = wallet_node.wallet_state_manager.main_wallet
        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(
            PeerInfo(self_hostname, uint16(fn_server._port)), None)
        for i in range(0, num_blocks):
            await full_node_api.farm_new_transaction_block(
                FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_pool_reward(uint32(i)) +
            calculate_base_farmer_reward(uint32(i))
            for i in range(1, num_blocks)
        ])

        await time_out_assert(5, wallet.get_confirmed_balance, funds)

        await full_node_api.reorg_from_index_to_new_index(
            ReorgProtocol(uint32(3), uint32(num_blocks + 6), 32 * b"0"))

        funds = sum([
            calculate_pool_reward(uint32(i)) +
            calculate_base_farmer_reward(uint32(i))
            for i in range(1, num_blocks - 2)
        ])

        await time_out_assert(5, wallet.get_confirmed_balance, funds)
Ejemplo n.º 26
0
    async def test_get_wallet_for_colour(self, two_wallet_nodes):
        num_blocks = 3
        full_nodes, wallets = two_wallet_nodes
        full_node_api = full_nodes[0]
        full_node_server = full_node_api.server
        wallet_node, server_2 = wallets[0]
        wallet = wallet_node.wallet_state_manager.main_wallet

        ph = await wallet.get_new_puzzlehash()

        await server_2.start_client(
            PeerInfo("localhost", uint16(full_node_server._port)), None)

        for i in range(1, num_blocks):
            await full_node_api.farm_new_transaction_block(
                FarmNewBlockProtocol(ph))

        funds = sum([
            calculate_pool_reward(uint32(i)) +
            calculate_base_farmer_reward(uint32(i))
            for i in range(1, num_blocks - 1)
        ])

        await time_out_assert(15, wallet.get_confirmed_balance, funds)

        cc_wallet: CCWallet = await CCWallet.create_new_cc(
            wallet_node.wallet_state_manager, wallet, uint64(100))

        for i in range(1, num_blocks):
            await full_node_api.farm_new_transaction_block(
                FarmNewBlockProtocol(32 * b"0"))

        colour = cc_wallet.get_colour()
        assert await wallet_node.wallet_state_manager.get_wallet_for_colour(
            colour) == cc_wallet
Ejemplo n.º 27
0
async def get_login_link(launcher_id_str: str) -> None:
    launcher_id: bytes32 = bytes32.from_hexstr(launcher_id_str)
    config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
    self_hostname = config["self_hostname"]
    farmer_rpc_port = config["farmer"]["rpc_port"]
    farmer_client = await FarmerRpcClient.create(self_hostname,
                                                 uint16(farmer_rpc_port),
                                                 DEFAULT_ROOT_PATH, config)
    try:
        login_link: Optional[str] = await farmer_client.get_pool_login_link(
            launcher_id)
        if login_link is None:
            print("Was not able to get login link.")
        else:
            print(login_link)
    except Exception as e:
        if isinstance(e, aiohttp.ClientConnectorError):
            print(
                f"Connection error. Check if farmer is running at {farmer_rpc_port}."
                f" You can run the farmer by:\n    chia start farmer-only")
        else:
            print(f"Exception from 'farmer' {e}")
    finally:
        farmer_client.close()
        await farmer_client.await_closed()
Ejemplo n.º 28
0
    async def test_block_ses_mismatch(self, two_nodes, default_1000_blocks):
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = default_1000_blocks

        for block in blocks[:501]:
            await full_node_1.full_node.respond_block(
                full_node_protocol.RespondBlock(block))

        peak1 = full_node_1.full_node.blockchain.get_peak()
        full_node_2.full_node.sync_store.set_long_sync(True)
        await server_2.start_client(
            PeerInfo(self_hostname, uint16(server_1._port)),
            full_node_2.full_node.on_connect)
        wp = await full_node_1.full_node.weight_proof_handler.get_proof_of_weight(
            peak1.header_hash)
        summaries1, _ = _validate_sub_epoch_summaries(
            full_node_1.full_node.weight_proof_handler.constants, wp)
        summaries2 = summaries1
        s = summaries1[1]
        # change summary so check would fail on 2 sub epoch
        summaries2[1] = SubEpochSummary(
            s.prev_subepoch_summary_hash,
            s.reward_chain_hash,
            s.num_blocks_overflow,
            s.new_difficulty * 2,
            s.new_sub_slot_iters * 2,
        )
        await full_node_2.full_node.sync_from_fork_point(
            0, 500, peak1.header_hash, summaries2)
        log.info(
            f"full node height {full_node_2.full_node.blockchain.get_peak().height}"
        )
        assert node_height_between(full_node_2, 320, 400)
Ejemplo n.º 29
0
    async def test_basic_sync_wallet(self, wallet_node, default_400_blocks):

        full_node_api, wallet_node, full_node_server, wallet_server = wallet_node

        for block in default_400_blocks:
            await full_node_api.full_node.respond_block(
                full_node_protocol.RespondBlock(block))

        await wallet_server.start_client(
            PeerInfo(self_hostname, uint16(full_node_server._port)), None)

        # The second node should eventually catch up to the first one, and have the
        # same tip at height num_blocks - 1.
        await time_out_assert(100, wallet_height_at_least, True, wallet_node,
                              len(default_400_blocks) - 1)

        # Tests a reorg with the wallet
        num_blocks = 30
        blocks_reorg = bt.get_consecutive_blocks(
            num_blocks, block_list_input=default_400_blocks[:-5])
        for i in range(1, len(blocks_reorg)):
            await full_node_api.full_node.respond_block(
                full_node_protocol.RespondBlock(blocks_reorg[i]))

        await disconnect_all_and_reconnect(wallet_server, full_node_server)

        await time_out_assert(100, wallet_height_at_least, True, wallet_node,
                              len(default_400_blocks) + num_blocks - 5 - 1)
Ejemplo n.º 30
0
def get_host_addr(host: Union[PeerInfo, str],
                  prefer_ipv6: Optional[bool]) -> str:
    # If there was no preference passed in (from config), set the system-wise
    # default here.  Not a great place to locate a default value, and we should
    # probabaly do something to write it into the config, but.  For now...
    if prefer_ipv6 is None:
        prefer_ipv6 = False
    # Use PeerInfo.is_valid() to see if it's already an address
    if isinstance(host, PeerInfo):
        hoststr = host.host
        if host.is_valid(True):
            return hoststr
    else:
        hoststr = host
        if PeerInfo(hoststr, uint16(0)).is_valid(True):
            return hoststr
    addrset: List[Tuple["socket.AddressFamily", "socket.SocketKind", int, str,
                        Union[Tuple[str, int],
                              Tuple[str, int, int,
                                    int]]]] = socket.getaddrinfo(
                                        hoststr, None)
    # Addrset is never empty, an exception is thrown or data is returned.
    for t in addrset:
        if prefer_ipv6 and t[0] == socket.AF_INET6:
            return t[4][0]
        if not prefer_ipv6 and t[0] == socket.AF_INET:
            return t[4][0]
    # If neither matched preference, just return the first available
    return addrset[0][4][0]