Esempio n. 1
0
async def test_farmer_signage_point_endpoints(environment):
    (
        farmer_service,
        farmer_rpc_api,
        farmer_rpc_client,
        harvester_service,
        harvester_rpc_api,
        harvester_rpc_client,
    ) = environment
    farmer_api = farmer_service._api

    assert (await farmer_rpc_client.get_signage_point(std_hash(b"2"))) is None
    assert len(await farmer_rpc_client.get_signage_points()) == 0

    async def have_signage_points():
        return len(await farmer_rpc_client.get_signage_points()) > 0

    sp = farmer_protocol.NewSignagePoint(std_hash(b"1"), std_hash(b"2"),
                                         std_hash(b"3"), uint64(1),
                                         uint64(1000000), uint8(2))
    await farmer_api.new_signage_point(sp)

    await time_out_assert(5, have_signage_points, True)
    assert (await
            farmer_rpc_client.get_signage_point(std_hash(b"2"))) is not None
Esempio n. 2
0
    async def create_wallet_backup(self, file_path: Path):
        all_wallets = await self.get_all_wallet_info_entries()
        for wallet in all_wallets:
            if wallet.id == 1:
                all_wallets.remove(wallet)
                break

        backup_pk = master_sk_to_backup_sk(self.private_key)
        now = uint64(int(time.time()))
        wallet_backup = WalletInfoBackup(all_wallets)

        backup: Dict[str, Any] = {}

        data = wallet_backup.to_json_dict()
        data["version"] = __version__
        data["fingerprint"] = self.private_key.get_g1().get_fingerprint()
        data["timestamp"] = now
        data["start_height"] = await self.get_start_height()
        key_base_64 = base64.b64encode(bytes(backup_pk))
        f = Fernet(key_base_64)
        data_bytes = json.dumps(data).encode()
        encrypted = f.encrypt(data_bytes)

        meta_data: Dict[str, Any] = {"timestamp": now, "pubkey": bytes(backup_pk.get_g1()).hex()}

        meta_data_bytes = json.dumps(meta_data).encode()
        signature = bytes(AugSchemeMPL.sign(backup_pk, std_hash(encrypted) + std_hash(meta_data_bytes))).hex()

        backup["data"] = encrypted.decode()
        backup["meta_data"] = meta_data
        backup["signature"] = signature

        backup_file_text = json.dumps(backup)
        file_path.write_text(backup_file_text)
Esempio n. 3
0
def open_backup_file(file_path, private_key):
    backup_file_text = file_path.read_text()
    backup_file_json = json.loads(backup_file_text)
    meta_data = backup_file_json["meta_data"]
    meta_data_bytes = json.dumps(meta_data).encode()
    sig = backup_file_json["signature"]

    backup_pk = master_sk_to_backup_sk(private_key)
    my_pubkey = backup_pk.get_g1()
    key_base_64 = base64.b64encode(bytes(backup_pk))
    f = Fernet(key_base_64)

    encrypted_data = backup_file_json["data"].encode()
    msg = std_hash(encrypted_data) + std_hash(meta_data_bytes)

    signature = SignatureMPL.from_bytes(hexstr_to_bytes(sig))
    pubkey = PublicKeyMPL.from_bytes(hexstr_to_bytes(meta_data["pubkey"]))

    sig_match_my = AugSchemeMPL.verify(my_pubkey, msg, signature)
    sig_match_backup = AugSchemeMPL.verify(pubkey, msg, signature)

    assert sig_match_my is True
    assert sig_match_backup is True

    data_bytes = f.decrypt(encrypted_data)
    data_text = data_bytes.decode()
    data_json = json.loads(data_text)
    unencrypted = {}
    unencrypted["data"] = data_json
    unencrypted["meta_data"] = meta_data
    return unencrypted
Esempio n. 4
0
def get_pairings(cache: LRUCache, pks: List[G1Element], msgs: List[bytes],
                 force_cache: bool) -> List[GTElement]:
    pairings: List[Optional[GTElement]] = []
    missing_count: int = 0
    for pk, msg in zip(pks, msgs):
        aug_msg: bytes = bytes(pk) + msg
        h: bytes = bytes(std_hash(aug_msg))
        pairing: Optional[GTElement] = cache.get(h)
        if not force_cache and pairing is None:
            missing_count += 1
            # Heuristic to avoid more expensive sig validation with pairing
            # cache when it's empty and cached pairings won't be useful later
            # (e.g. while syncing)
            if missing_count > len(pks) // 2:
                return []
        pairings.append(pairing)

    for i, pairing in enumerate(pairings):
        if pairing is None:
            aug_msg = bytes(pks[i]) + msgs[i]
            aug_hash: G2Element = AugSchemeMPL.g2_from_message(aug_msg)
            pairing = pks[i].pair(aug_hash)

            h = bytes(std_hash(aug_msg))
            cache.put(h, pairing)
            pairings[i] = pairing

    return pairings
Esempio n. 5
0
 def __init__(self, rci: List[Coin], height: uint32, timestamp: uint64):
     self.reward_claims_incorporated = rci
     self.height = height
     self.prev_transaction_block_height = uint32(height - 1) if height > 0 else 0
     self.timestamp = timestamp
     self.is_transaction_block = True
     self.header_hash = std_hash(bytes(height))
     self.prev_transaction_block_hash = std_hash(std_hash(height))
Esempio n. 6
0
 def get_tried_bucket(self, key: int) -> int:
     hash1 = int.from_bytes(
         bytes(std_hash(key.to_bytes(32, byteorder="big") + self.peer_info.get_key())[:8]),
         byteorder="big",
     )
     hash1 = hash1 % TRIED_BUCKETS_PER_GROUP
     hash2 = int.from_bytes(
         bytes(std_hash(key.to_bytes(32, byteorder="big") + self.peer_info.get_group() + bytes([hash1]))[:8]),
         byteorder="big",
     )
     return hash2 % TRIED_BUCKET_COUNT
Esempio n. 7
0
    def test_win_percentage(self):
        """
        Tests that the percentage of blocks won is proportional to the space of each farmer,
        with the assumption that all farmers have access to the same VDF speed.
        """
        farmer_ks = {
            uint8(32): 100,
            uint8(33): 100,
            uint8(34): 100,
            uint8(35): 100,
            uint8(36): 100,
        }
        farmer_space = {
            k: _expected_plot_size(uint8(k)) * count
            for k, count in farmer_ks.items()
        }
        total_space = sum(farmer_space.values())
        percentage_space = {
            k: float(sp / total_space)
            for k, sp in farmer_space.items()
        }
        wins = {k: 0 for k in farmer_ks.keys()}
        total_slots = 50
        num_sps = 16
        sp_interval_iters = uint64(100000000 // 32)
        difficulty = uint64(500000000000)

        for slot_index in range(total_slots):
            total_wins_in_slot = 0
            for sp_index in range(num_sps):
                sp_hash = std_hash(
                    slot_index.to_bytes(4, "big") +
                    sp_index.to_bytes(4, "big"))
                for k, count in farmer_ks.items():
                    for farmer_index in range(count):
                        quality = std_hash(
                            slot_index.to_bytes(4, "big") +
                            k.to_bytes(1, "big") + bytes(farmer_index))
                        required_iters = calculate_iterations_quality(
                            2**25, quality, k, difficulty, sp_hash)
                        if required_iters < sp_interval_iters:
                            wins[k] += 1
                            total_wins_in_slot += 1

        win_percentage = {
            k: wins[k] / sum(wins.values())
            for k in farmer_ks.keys()
        }
        for k in farmer_ks.keys():
            # Win rate is proportional to percentage of space
            assert abs(win_percentage[k] - percentage_space[k]) < 0.01
Esempio n. 8
0
 def get_new_bucket(self, key: int, src_peer: Optional[PeerInfo] = None) -> int:
     if src_peer is None:
         src_peer = self.src
     assert src_peer is not None
     hash1 = int.from_bytes(
         bytes(std_hash(key.to_bytes(32, byteorder="big") + self.peer_info.get_group() + src_peer.get_group())[:8]),
         byteorder="big",
     )
     hash1 = hash1 % NEW_BUCKETS_PER_SOURCE_GROUP
     hash2 = int.from_bytes(
         bytes(std_hash(key.to_bytes(32, byteorder="big") + src_peer.get_group() + bytes([hash1]))[:8]),
         byteorder="big",
     )
     return hash2 % NEW_BUCKET_COUNT
Esempio n. 9
0
    async def get_farmer(self, request_obj) -> web.Response:
        # TODO(pool): add rate limiting
        launcher_id = 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 = std_hash(launcher_id + bytes(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)
Esempio n. 10
0
    async def get_login(self, request_obj) -> web.Response:
        # TODO(pool): add rate limiting
        launcher_id = request_obj.rel_url.query["launcher_id"]
        authentication_token = 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} unknown.")

        # Validate provided signature
        signature = request_obj.rel_url.query["signature"]
        message = std_hash(launcher_id + bytes(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}.",
            )

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

        # TODO(pool) Do what ever you like with the successful login
        return obj_to_response({"login_data", "Put server side login information here?"})
Esempio n. 11
0
def claim_p2_singleton(
    p2_singleton_coin: Coin,
    singleton_inner_puzhash: bytes32,
    launcher_id: bytes32,
    delay_time: Optional[uint64] = None,
    delay_ph: Optional[bytes32] = None,
) -> Tuple[Program, Program, CoinSpend]:
    assertion = Program.to([
        ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT,
        std_hash(p2_singleton_coin.name() + b"$")
    ])
    announcement = Program.to(
        [ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT,
         p2_singleton_coin.name()])
    if delay_time is None or delay_ph is None:
        puzzle: Program = pay_to_singleton_puzzle(launcher_id)
    else:
        puzzle = pay_to_singleton_or_delay_puzzle(
            launcher_id,
            delay_time,
            delay_ph,
        )
    claim_coinsol = CoinSpend(
        p2_singleton_coin,
        puzzle,
        solution_for_p2_singleton(p2_singleton_coin, singleton_inner_puzhash),
    )
    return assertion, announcement, claim_coinsol
Esempio n. 12
0
async def download_backup(host: str, private_key: PrivateKey):
    session = aiohttp.ClientSession()
    try:
        backup_privkey = master_sk_to_backup_sk(private_key)
        backup_pubkey = bytes(backup_privkey.get_g1()).hex()
        # Get nonce
        nonce_request = {"pubkey": backup_pubkey}
        nonce_url = f"{host}/get_download_nonce"
        nonce_response = await post(session, nonce_url, nonce_request)
        nonce = nonce_response["nonce"]

        # Sign nonce
        signature = bytes(AugSchemeMPL.sign(backup_privkey, std_hash(hexstr_to_bytes(nonce)))).hex()
        # Request backup url
        get_backup_url = f"{host}/download_backup"
        backup_request = {"pubkey": backup_pubkey, "signature": signature}
        backup_response = await post(session, get_backup_url, backup_request)

        if backup_response["success"] is False:
            raise ValueError("No backup on backup service")

        # Download from s3
        backup_url = backup_response["url"]
        backup_text = await get(session, backup_url)
        await session.close()
        return backup_text
    except Exception as e:
        await session.close()
        # Pass exception
        raise e
Esempio n. 13
0
async def start_pool_server(args):
    global server
    global runner
    private_key: PrivateKey = AugSchemeMPL.key_gen(std_hash(b"123"))
    config = load_config(DEFAULT_ROOT_PATH, "config.yaml")
    overrides = config["network_overrides"]["constants"][
        config["selected_network"]]
    constants: ConsensusConstants = DEFAULT_CONSTANTS.replace_str_to_bytes(
        **overrides)
    server = PoolServer(private_key, config, constants, args)
    await server.start()

    # TODO(pool): support TLS
    app = web.Application()
    app.add_routes([
        web.get("/", server.wrap_http_handler(server.index)),
        web.get("/get_pool_info",
                server.wrap_http_handler(server.get_pool_info)),
        web.post("/submit_partial",
                 server.wrap_http_handler(server.submit_partial)),
    ])
    runner = aiohttp.web.AppRunner(app, access_log=None)
    await runner.setup()
    site = aiohttp.web.TCPSite(runner, config["self_hostname"], int(3000))
    await site.start()
    await asyncio.sleep(10000000)
Esempio n. 14
0
def bytes_from_mnemonic(mnemonic_str: str) -> bytes:
    mnemonic: List[str] = mnemonic_str.split(" ")
    if len(mnemonic) not in [12, 15, 18, 21, 24]:
        raise ValueError("Invalid mnemonic length")

    word_list = {
        word: i
        for i, word in enumerate(bip39_word_list().splitlines())
    }
    bit_array = BitArray()
    for i in range(0, len(mnemonic)):
        word = mnemonic[i]
        if word not in word_list:
            raise ValueError(
                f"'{word}' is not in the mnemonic dictionary; may be misspelled"
            )
        value = word_list[word]
        bit_array.append(BitArray(uint=value, length=11))

    CS: int = len(mnemonic) // 3
    ENT: int = len(mnemonic) * 11 - CS
    assert len(bit_array) == len(mnemonic) * 11
    assert ENT % 32 == 0

    entropy_bytes = bit_array[:ENT].bytes
    checksum_bytes = bit_array[ENT:]
    checksum = BitArray(std_hash(entropy_bytes))[:CS]

    assert len(checksum_bytes) == CS

    if checksum != checksum_bytes:
        raise ValueError("Invalid order of mnemonic words")

    return entropy_bytes
Esempio n. 15
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
Esempio n. 16
0
def hash_coin_list(coin_list: List[Coin]) -> bytes32:
    coin_list.sort(key=lambda x: x.name_str, reverse=True)
    buffer = bytearray()

    for coin in coin_list:
        buffer.extend(coin.name())

    return std_hash(buffer)
Esempio n. 17
0
def coin_serialize(amount: uint64, clvm_serialize: bytes,
                   full_serialize: bytes):

    c = Coin(bytes32(b"a" * 32), bytes32(b"b" * 32), amount)
    expected_hash = (b"a" * 32) + (b"b" * 32) + clvm_serialize

    expected_serialization = (b"a" * 32) + (b"b" * 32) + full_serialize

    assert c.get_hash() == std_hash(expected_hash)
    assert c.name() == std_hash(expected_hash)
    f = io.BytesIO()
    c.stream(f)
    assert bytes(f.getvalue()) == expected_serialization

    # make sure the serialization round-trips
    f = io.BytesIO(expected_serialization)
    c2 = Coin.parse(f)
    assert c2 == c
Esempio n. 18
0
    def get_hash(self) -> bytes32:
        # This does not use streamable format for hashing, the amount is
        # serialized using CLVM integer format.

        # Note that int_to_bytes() will prepend a 0 to integers where the most
        # significant bit is set, to encode it as a positive number. This
        # despite "amount" being unsigned. This way, a CLVM program can generate
        # these hashes easily.
        return std_hash(self.parent_coin_info + self.puzzle_hash + int_to_bytes(self.amount))
Esempio n. 19
0
    async def combine_coins(self, coins):
        # Overall structure:
        # Create len-1 spends that just assert that the final coin is created with full value.
        # Create 1 spend for the final coin that asserts the other spends occurred and
        # Creates the new coin.

        beginning_balance = self.balance()
        beginning_coins = len(self.usable_coins)

        # We need the final coin to know what the announced coin name will be.
        final_coin = CoinWrapper(coins[-1].name(), self.puzzle_hash,
                                 sum(map(lambda x: x.amount, coins)),
                                 self.puzzle)

        destroyed_coin_solutions = []

        # Each coin wants agg_sig_me so we aggregate them at the end.
        signatures = []

        for c in coins[:-1]:
            announce_conditions = [
                # Each coin expects the final coin creation announcement
                [
                    ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT,
                    std_hash(coins[-1].name() + final_coin.name())
                ]
            ]

            coin_solution, signature = c.create_standard_spend(
                self.sk_, announce_conditions)
            destroyed_coin_solutions.append(coin_solution)
            signatures.append(signature)

        final_coin_creation = [
            [ConditionOpcode.CREATE_COIN_ANNOUNCEMENT,
             final_coin.name()],
            [ConditionOpcode.CREATE_COIN, self.puzzle_hash, final_coin.amount],
        ]

        coin_solution, signature = coins[-1].create_standard_spend(
            self.sk_, final_coin_creation)
        destroyed_coin_solutions.append(coin_solution)
        signatures.append(signature)

        signature = AugSchemeMPL.aggregate(signatures)
        spend_bundle = SpendBundle(destroyed_coin_solutions, signature)

        pushed = await self.parent.push_tx(spend_bundle)

        # We should have the same amount of money.
        assert beginning_balance == self.balance()
        # We should have shredded n-1 coins and replaced one.
        assert len(self.usable_coins) == beginning_coins - (len(coins) - 1)

        return SpendResult(pushed)
Esempio n. 20
0
async def setup_simulators_and_wallets(
    simulator_count: int,
    wallet_count: int,
    dic: Dict,
    starting_height=None,
    key_seed=None,
    starting_port=50000,
    initial_num_public_keys=5,
):
    with TempKeyring() as keychain1, TempKeyring() as keychain2:
        simulators: List[FullNodeAPI] = []
        wallets = []
        node_iters = []

        consensus_constants = constants_for_dic(dic)
        for index in range(0, simulator_count):
            port = starting_port + index
            db_name = f"blockchain_test_{port}.db"
            bt_tools = await create_block_tools_async(
                consensus_constants, const_dict=dic, keychain=keychain1
            )  # block tools modifies constants
            sim = setup_full_node(
                bt_tools.constants,
                db_name,
                port,
                bt_tools,
                simulator=True,
            )
            simulators.append(await sim.__anext__())
            node_iters.append(sim)

        for index in range(0, wallet_count):
            if key_seed is None:
                seed = std_hash(uint32(index))
            else:
                seed = key_seed
            port = starting_port + 5000 + index
            bt_tools = await create_block_tools_async(
                consensus_constants, const_dict=dic, keychain=keychain2
            )  # block tools modifies constants
            wlt = setup_wallet_node(
                port,
                bt_tools.constants,
                bt_tools,
                None,
                key_seed=seed,
                starting_height=starting_height,
                initial_num_public_keys=initial_num_public_keys,
            )
            wallets.append(await wlt.__anext__())
            node_iters.append(wlt)

        yield simulators, wallets

        await _teardown_nodes(node_iters)
Esempio n. 21
0
 def get_bucket_position(self, key: int, is_new: bool, nBucket: int) -> int:
     ch = "N" if is_new else "K"
     hash1 = int.from_bytes(
         bytes(
             std_hash(
                 key.to_bytes(32, byteorder="big") + ch.encode() +
                 nBucket.to_bytes(3, byteorder="big") +
                 self.peer_info.get_key())[:8]),
         byteorder="big",
     )
     return hash1 % BUCKET_SIZE
Esempio n. 22
0
 async def _address_relay(self):
     while not self.is_closed:
         try:
             try:
                 relay_peer, num_peers = await self.relay_queue.get()
             except asyncio.CancelledError:
                 return None
             relay_peer_info = PeerInfo(relay_peer.host, relay_peer.port)
             if not relay_peer_info.is_valid():
                 continue
             # https://en.bitcoin.it/wiki/Satoshi_Client_Node_Discovery#Address_Relay
             connections = self.server.get_full_node_connections()
             hashes = []
             cur_day = int(time.time()) // (24 * 60 * 60)
             for connection in connections:
                 peer_info = connection.get_peer_info()
                 if peer_info is None:
                     continue
                 cur_hash = int.from_bytes(
                     bytes(
                         std_hash(
                             self.key.to_bytes(32, byteorder="big")
                             + peer_info.get_key()
                             + cur_day.to_bytes(3, byteorder="big")
                         )
                     ),
                     byteorder="big",
                 )
                 hashes.append((cur_hash, connection))
             hashes.sort(key=lambda x: x[0])
             for index, (_, connection) in enumerate(hashes):
                 if index >= num_peers:
                     break
                 peer_info = connection.get_peer_info()
                 pair = (peer_info.host, peer_info.port)
                 async with self.lock:
                     if pair in self.neighbour_known_peers and relay_peer.host in self.neighbour_known_peers[pair]:
                         continue
                     if pair not in self.neighbour_known_peers:
                         self.neighbour_known_peers[pair] = set()
                     self.neighbour_known_peers[pair].add(relay_peer.host)
                 if connection.peer_node_id is None:
                     continue
                 msg = make_msg(
                     ProtocolMessageTypes.respond_peers,
                     full_node_protocol.RespondPeers([relay_peer]),
                 )
                 await connection.send_message(msg)
         except Exception as e:
             self.log.error(f"Exception in address relay: {e}")
             self.log.error(f"Traceback: {traceback.format_exc()}")
Esempio n. 23
0
def _tree_hash(node: SExp, precalculated: Set[bytes32]) -> bytes32:
    """
    Hash values in `precalculated` are presumed to have been hashed already.
    """
    if node.listp():
        left = _tree_hash(node.first(), precalculated)
        right = _tree_hash(node.rest(), precalculated)
        s = b"\2" + left + right
    else:
        atom = node.as_atom()
        if atom in precalculated:
            return bytes32(atom)
        s = b"\1" + atom
    return bytes32(std_hash(s))
Esempio n. 24
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)
Esempio n. 25
0
 def handle_sexp(sexp_stack, op_stack, precalculated: Set[bytes32]) -> None:
     sexp = sexp_stack.pop()
     if sexp.pair:
         p0, p1 = sexp.pair
         sexp_stack.append(p0)
         sexp_stack.append(p1)
         op_stack.append(handle_pair)
         op_stack.append(handle_sexp)
         op_stack.append(roll)
         op_stack.append(handle_sexp)
     else:
         if sexp.atom in precalculated:
             r = sexp.atom
         else:
             r = std_hash(b"\1" + sexp.atom)
         sexp_stack.append(r)
def get_name_puzzle_conditions(block_program: SerializedProgram,
                               safe_mode: bool):
    # TODO: allow generator mod to take something (future)
    # TODO: write more tests
    block_program_args = SerializedProgram.from_bytes(b"\x80")

    try:
        if safe_mode:
            cost, result = GENERATOR_MOD.run_safe_with_cost(
                block_program, block_program_args)
        else:
            cost, result = GENERATOR_MOD.run_with_cost(block_program,
                                                       block_program_args)
        npc_list = []
        opcodes = set(item.value for item in ConditionOpcode)
        for res in result.as_iter():
            conditions_list = []
            name = std_hash(
                bytes(res.first().first().as_atom() +
                      res.first().rest().first().as_atom() +
                      res.first().rest().rest().first().as_atom()))
            puzzle_hash = bytes32(res.first().rest().first().as_atom())
            for cond in res.rest().first().as_iter():
                if cond.first().as_atom() in opcodes:
                    opcode = ConditionOpcode(cond.first().as_atom())
                elif not safe_mode:
                    opcode = ConditionOpcode.UNKNOWN
                else:
                    return "Unknown operator in safe mode.", None, None
                if len(list(cond.as_iter())) > 1:
                    cond_var_list = []
                    for cond_1 in cond.rest().as_iter():
                        cond_var_list.append(cond_1.as_atom())
                    cvl = ConditionVarPair(opcode, cond_var_list)
                else:
                    cvl = ConditionVarPair(opcode, [])
                conditions_list.append(cvl)
            conditions_dict = conditions_by_opcode(conditions_list)
            if conditions_dict is None:
                conditions_dict = {}
            npc_list.append(
                NPC(name, puzzle_hash,
                    [(a, b) for a, b in conditions_dict.items()]))
        return None, npc_list, uint64(cost)
    except Exception:
        tb = traceback.format_exc()
        return tb, None, None
Esempio n. 27
0
def calculate_iterations_quality(
    difficulty_constant_factor: uint128,
    quality_string: bytes32,
    size: int,
    difficulty: uint64,
    cc_sp_output_hash: bytes32,
) -> uint64:
    """
    Calculates the number of iterations from the quality. This is derives as the difficulty times the constant factor
    times a random number between 0 and 1 (based on quality string), divided by plot size.
    """
    sp_quality_string: bytes32 = std_hash(quality_string + cc_sp_output_hash)

    iters = uint64(
        int(difficulty) * int(difficulty_constant_factor) *
        int.from_bytes(sp_quality_string, "big", signed=False) //
        (int(pow(2, 256)) * int(_expected_plot_size(size))))
    return max(iters, uint64(1))
Esempio n. 28
0
async def respond_transaction(
    node: FullNodeAPI,
    tx: full_node_protocol.RespondTransaction,
    peer: ws.WSChiaConnection,
    tx_bytes: bytes = b"",
    test: bool = False,
) -> Tuple[MempoolInclusionStatus, Optional[Err]]:
    """
    Receives a full transaction from peer.
    If tx is added to mempool, send tx_id to others. (new_transaction)
    """
    assert tx_bytes != b""
    spend_name = std_hash(tx_bytes)
    if spend_name in node.full_node.full_node_store.pending_tx_request:
        node.full_node.full_node_store.pending_tx_request.pop(spend_name)
    if spend_name in node.full_node.full_node_store.peers_with_tx:
        node.full_node.full_node_store.peers_with_tx.pop(spend_name)
    return await node.full_node.respond_transaction(tx.transaction, spend_name, peer, test)
Esempio n. 29
0
def claim_p2_singleton(
    p2_singleton_coin: Coin,
    singleton_inner_puzhash: bytes32,
    launcher_id: bytes32,
) -> Tuple[Program, Program, CoinSolution]:
    assertion = Program.to([
        ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT,
        std_hash(p2_singleton_coin.name() + b"$")
    ])
    announcement = Program.to(
        [ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT,
         p2_singleton_coin.name()])
    claim_coinsol = CoinSolution(
        p2_singleton_coin,
        pay_to_singleton_puzzle(launcher_id),
        solution_for_p2_singleton(p2_singleton_coin, singleton_inner_puzhash),
    )
    return assertion, announcement, claim_coinsol
Esempio n. 30
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