Esempio n. 1
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)

        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 == []
Esempio n. 2
0
    async def new_signage_point(self, new_signage_point: farmer_protocol.NewSignagePoint):
        message = harvester_protocol.NewSignagePointHarvester(
            new_signage_point.challenge_hash,
            new_signage_point.difficulty,
            new_signage_point.sub_slot_iters,
            new_signage_point.signage_point_index,
            new_signage_point.challenge_chain_sp,
        )

        msg = make_msg(ProtocolMessageTypes.new_signage_point_harvester, message)
        await self.farmer.server.send_to_all([msg], NodeType.HARVESTER)
        if new_signage_point.challenge_chain_sp not in self.farmer.sps:
            self.farmer.sps[new_signage_point.challenge_chain_sp] = []
        self.farmer.sps[new_signage_point.challenge_chain_sp].append(new_signage_point)
        self.farmer.cache_add_time[new_signage_point.challenge_chain_sp] = uint64(int(time.time()))
        self.farmer.state_changed("new_signage_point", {"sp_hash": new_signage_point.challenge_chain_sp})
Esempio n. 3
0
def get_future_reward_coins(block: FullBlock) -> Tuple[Coin, Coin]:
    pool_amount = calculate_pool_reward(block.height)
    farmer_amount = calculate_base_farmer_reward(block.height)
    if block.is_transaction_block():
        assert block.transactions_info is not None
        farmer_amount = uint64(farmer_amount + block.transactions_info.fees)
    pool_coin: Coin = create_pool_coin(
        block.height, block.foliage.foliage_block_data.pool_target.puzzle_hash,
        pool_amount, constants.GENESIS_CHALLENGE)
    farmer_coin: Coin = create_farmer_coin(
        block.height,
        block.foliage.foliage_block_data.farmer_reward_puzzle_hash,
        farmer_amount,
        constants.GENESIS_CHALLENGE,
    )
    return pool_coin, farmer_coin
def mempool_assert_relative_time_exceeds(condition: ConditionWithArgs,
                                         unspent: CoinRecord,
                                         timestamp: uint64) -> Optional[Err]:
    """
    Check if the current time in seconds exceeds the time specified by condition
    """
    try:
        expected_seconds = int_from_bytes(condition.vars[0])
    except ValueError:
        return Err.INVALID_CONDITION

    if timestamp is None:
        timestamp = uint64(int(time.time()))
    if timestamp < expected_seconds + unspent.timestamp:
        return Err.ASSERT_SECONDS_RELATIVE_FAILED
    return None
Esempio n. 5
0
    async def get_farmer_points_and_payout_instructions(self) -> List[Tuple[uint64, bytes]]:
        cursor = await self.connection.execute(f"SELECT points, payout_instructions from farmer")
        rows = await cursor.fetchall()
        accumulated: Dict[bytes32, uint64] = {}
        for row in rows:
            points: uint64 = uint64(row[0])
            ph: bytes32 = bytes32(bytes.fromhex(row[1]))
            if ph in accumulated:
                accumulated[ph] += points
            else:
                accumulated[ph] = points

        ret: List[Tuple[uint64, bytes32]] = []
        for ph, total_points in accumulated.items():
            ret.append((total_points, ph))
        return ret
def mempool_assert_absolute_time_exceeds(
        condition: ConditionWithArgs,
        timestamp: Optional[uint64] = None) -> Optional[Err]:
    """
    Check if the current time in millis exceeds the time specified by condition
    """
    try:
        expected_mili_time = int_from_bytes(condition.vars[0])
    except ValueError:
        return Err.INVALID_CONDITION

    if timestamp is None:
        timestamp = uint64(int(time.time() * 1000))
    if timestamp < expected_mili_time:
        return Err.ASSERT_SECONDS_ABSOLUTE_FAILED
    return None
    async def test_assert_time_exceeds_both_cases(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_height = blocks[-1].height if len(blocks) > 0 else -1
        blocks = bt.get_consecutive_blocks(
            3,
            block_list_input=blocks,
            guarantee_transaction_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        peer = await connect_and_get_peer(server_1, server_2)

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

        await time_out_assert(60, node_height_at_least, True, full_node_1,
                              start_height + 3)

        time_now = uint64(int(time() * 1000))
        time_now_plus_3 = time_now + 3000

        cvp = ConditionVarPair(ConditionOpcode.ASSERT_SECONDS_NOW_EXCEEDS,
                               [time_now_plus_3.to_bytes(8, "big")])
        dic = {cvp.opcode: [cvp]}

        spend_bundle1 = generate_test_spend_bundle(
            list(blocks[-1].get_included_reward_coins())[0], dic)

        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle1)
        await full_node_1.respond_transaction(tx1, peer)

        # Sleep so that 3 sec passes
        await asyncio.sleep(3)

        tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle1)
        await full_node_1.respond_transaction(tx2, peer)

        sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(
            spend_bundle1.name())

        assert sb1 is spend_bundle1
Esempio n. 8
0
    def _can_infuse_unfinished_block(self, block: timelord_protocol.NewUnfinishedBlockTimelord) -> Optional[uint64]:
        assert self.last_state is not None
        sub_slot_iters = self.last_state.get_sub_slot_iters()
        difficulty = self.last_state.get_difficulty()
        ip_iters = self.last_state.get_last_ip()
        rc_block = block.reward_chain_block
        try:
            block_sp_iters, block_ip_iters = iters_from_block(
                self.constants,
                rc_block,
                sub_slot_iters,
                difficulty,
            )
        except Exception as e:
            log.warning(f"Received invalid unfinished block: {e}.")
            return None
        block_sp_total_iters = self.last_state.total_iters - ip_iters + block_sp_iters
        if is_overflow_block(self.constants, block.reward_chain_block.signage_point_index):
            block_sp_total_iters -= self.last_state.get_sub_slot_iters()
        found_index = -1
        for index, (rc, total_iters) in enumerate(self.last_state.reward_challenge_cache):
            if rc == block.rc_prev:
                found_index = index
                break
        if found_index == -1:
            log.warning(f"Will not infuse {block.rc_prev} because its reward chain challenge is not in the chain")
            return None

        new_block_iters = uint64(block_ip_iters - ip_iters)
        if len(self.last_state.reward_challenge_cache) > found_index + 1:
            if self.last_state.reward_challenge_cache[found_index + 1][1] < block_sp_total_iters:
                log.warning(
                    f"Will not infuse unfinished block {block.rc_prev} sp total iters {block_sp_total_iters}, "
                    f"because there is another infusion before its SP"
                )
                return None
            if self.last_state.reward_challenge_cache[found_index][1] > block_sp_total_iters:
                if not is_overflow_block(self.constants, block.reward_chain_block.signage_point_index):
                    log.error(
                        f"Will not infuse unfinished block {block.rc_prev}, sp total iters: {block_sp_total_iters}, "
                        f"because its iters are too low"
                    )
                return None

        if new_block_iters > 0:
            return new_block_iters
        return None
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
def spend_coin_to_singleton(
        puzzle_db: PuzzleDB, launcher_puzzle: Program, coin_store: CoinStore,
        now: CoinTimestamp) -> Tuple[List[Coin], List[CoinSpend]]:

    farmed_coin_amount = 100000
    metadata = [("foo", "bar")]

    now = CoinTimestamp(10012300, 1)
    farmed_coin = coin_store.farm_coin(ANYONE_CAN_SPEND_PUZZLE.get_tree_hash(),
                                       now,
                                       amount=farmed_coin_amount)
    now.seconds += 500
    now.height += 1

    launcher_amount: uint64 = uint64(1)
    launcher_puzzle = LAUNCHER_PUZZLE
    launcher_puzzle_hash = launcher_puzzle.get_tree_hash()
    initial_singleton_puzzle = adaptor_for_singleton_inner_puzzle(
        ANYONE_CAN_SPEND_PUZZLE)
    launcher_id, condition_list, launcher_spend_bundle = launcher_conditions_and_spend_bundle(
        puzzle_db, farmed_coin.name(), launcher_amount,
        initial_singleton_puzzle, metadata, launcher_puzzle)

    conditions = Program.to(condition_list)
    coin_spend = CoinSpend(farmed_coin, ANYONE_CAN_SPEND_PUZZLE, conditions)
    spend_bundle = SpendBundle.aggregate(
        [launcher_spend_bundle,
         SpendBundle([coin_spend], G2Element())])

    additions, removals = coin_store.update_coin_store_for_spend_bundle(
        spend_bundle, now, MAX_BLOCK_COST_CLVM, COST_PER_BYTE)

    launcher_coin = launcher_spend_bundle.coin_spends[0].coin

    assert_coin_spent(coin_store, launcher_coin)
    assert_coin_spent(coin_store, farmed_coin)

    singleton_expected_puzzle = singleton_puzzle(launcher_id,
                                                 launcher_puzzle_hash,
                                                 initial_singleton_puzzle)
    singleton_expected_puzzle_hash = singleton_expected_puzzle.get_tree_hash()
    expected_singleton_coin = Coin(launcher_coin.name(),
                                   singleton_expected_puzzle_hash,
                                   launcher_amount)
    assert_coin_spent(coin_store, expected_singleton_coin, is_spent=False)

    return additions, removals
Esempio n. 11
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}
Esempio n. 12
0
    async def test_double_spend_with_higher_fee(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()

        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_height = blocks[-1].height
        blocks = bt.get_consecutive_blocks(
            3,
            block_list_input=blocks,
            guarantee_transaction_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_block(
                full_node_protocol.RespondBlock(block))
        await time_out_assert(60, node_height_at_least, True, full_node_1,
                              start_height + 3)

        spend_bundle1 = generate_test_spend_bundle(
            list(blocks[-1].get_included_reward_coins())[0])
        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle1)

        await full_node_1.respond_transaction(tx1, peer)

        spend_bundle2 = generate_test_spend_bundle(list(
            blocks[-1].get_included_reward_coins())[0],
                                                   fee=uint64(1))

        assert spend_bundle2 is not None
        tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle2)

        await full_node_1.respond_transaction(tx2, peer)

        sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(
            spend_bundle1.name())
        sb2 = full_node_1.full_node.mempool_manager.get_spendbundle(
            spend_bundle2.name())

        assert sb1 is None
        assert sb2 == spend_bundle2
Esempio n. 13
0
def tx(info):
    j = json.dumps(info)
    m: Dict = eval(j)
    inputs: List = m.get("inputs")
    outputs: List = m.get("outputs")

    primaries = []
    for o in outputs:
        output: Dict = o
        address: str = output.get("address")
        value: float = output.get("value")
        primaries.append({
            "puzzlehash": decode_puzzle_hash(address),
            "amount": value
        })

    spends: List[CoinSolution] = []
    pks: List[str] = []
    first_spend = True
    for i in inputs:
        input: Dict = i
        pk: str = input.get("pk")
        pks.append(pk)
        txid: Dict = eval(input.get("txId"))
        parentCoinInfo = txid.get("parentCoinInfo")
        puzzleHash = txid.get("puzzleHash")
        amount = txid.get("amount")

        pa = bytes32(bytes.fromhex(parentCoinInfo[2:]))
        pu = bytes32(bytes.fromhex(puzzleHash[2:]))
        a = uint64(amount)
        coin: Coin = Coin(pa, pu, a)
        child_sk: PrivateKey = PrivateKey.from_bytes(bytes.fromhex(pk))
        child_public_key = child_sk.get_g1()
        puzzle = puzzle_for_pk(child_public_key)

        if first_spend:
            solution: Program = Wallet().make_solution(primaries=primaries)
            first_spend = False
        else:
            solution = Wallet().make_solution()
        spends.append(CoinSolution(coin, puzzle, solution))

    spend_bundle: SpendBundle = SpendBundle(spends, G2Element())
    # return json.dumps(spend_bundle.to_json_dict())
    return sign_tx(pks, spend_bundle)
Esempio n. 14
0
    async def setup_keys(self):
        self.all_root_sks: List[PrivateKey] = [
            sk for sk, _ in await self.get_all_private_keys()
        ]
        self._private_keys = [
            master_sk_to_farmer_sk(sk) for sk in self.all_root_sks
        ] + [master_sk_to_pool_sk(sk) for sk in self.all_root_sks]

        if len(self.get_public_keys()) == 0:
            error_str = "No keys exist. Please run 'chia keys generate' or open the UI."
            raise RuntimeError(error_str)

        # This is the farmer configuration
        self.farmer_target_encoded = self.config["xch_target_address"]
        self.farmer_target = decode_puzzle_hash(self.farmer_target_encoded)

        self.pool_public_keys = [
            G1Element.from_bytes(bytes.fromhex(pk))
            for pk in self.config["pool_public_keys"]
        ]

        # This is the self pooling configuration, which is only used for original self-pooled plots
        self.pool_target_encoded = self.pool_config["xch_target_address"]
        self.pool_target = decode_puzzle_hash(self.pool_target_encoded)
        self.pool_sks_map: Dict = {}
        for key in self.get_private_keys():
            self.pool_sks_map[bytes(key.get_g1())] = key

        assert len(self.farmer_target) == 32
        assert len(self.pool_target) == 32
        if len(self.pool_sks_map) == 0:
            error_str = "No keys exist. Please run 'chia keys generate' or open the UI."
            raise RuntimeError(error_str)

        # The variables below are for use with an actual pool

        # From p2_singleton_puzzle_hash to pool state dict
        self.pool_state: Dict[bytes32, Dict] = {}

        # From public key bytes to PrivateKey
        self.authentication_keys: Dict[bytes, PrivateKey] = {}

        # Last time we updated pool_state based on the config file
        self.last_config_access_time: uint64 = uint64(0)

        self.harvester_cache: Dict[str, Dict[str, HarvesterCacheEntry]] = {}
Esempio n. 15
0
    async def get_farmer(self, request_obj) -> web.Response:
        # TODO(pool): add rate limiting
        launcher_id: bytes32 = hexstr_to_bytes(
            request_obj.rel_url.query["launcher_id"])
        authentication_token = uint64(
            request_obj.rel_url.query["authentication_token"])

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

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

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

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

        self.pool.log.info(f"get_farmer response {response.to_json_dict()}, "
                           f"launcher_id: {launcher_id.hex()}")
        return obj_to_response(response)
Esempio n. 16
0
 async def cat_spend(
     self,
     wallet_id: str,
     amount: uint64,
     inner_address: str,
     fee: uint64 = uint64(0),
     memos: Optional[List[str]] = None,
 ) -> TransactionRecord:
     send_dict = {
         "wallet_id": wallet_id,
         "amount": amount,
         "inner_address": inner_address,
         "fee": fee,
         "memos": memos if memos else [],
     }
     res = await self.fetch("cat_spend", send_dict)
     return TransactionRecord.from_json_dict_convenience(res["transaction"])
Esempio n. 17
0
def do_inspect_coin_spend_cmd(ctx, spends, print_results=True, **kwargs):
    if kwargs and all([kwargs['puzzle_reveal'], kwargs['solution']]):
        if (not kwargs['coin']) and all(
            [kwargs['parent_id'], kwargs['puzzle_hash'], kwargs['amount']]):
            coin_spend_objs = [
                CoinSpend(
                    Coin(
                        bytes.fromhex(kwargs['parent_id']),
                        bytes.fromhex(kwargs['puzzle_hash']),
                        uint64(kwargs['amount']),
                    ),
                    parse_program(sanitize_bytes(kwargs['puzzle_reveal'])),
                    parse_program(sanitize_bytes(kwargs['solution'])),
                )
            ]
        elif kwargs['coin']:
            coin_spend_objs = [
                CoinSpend(
                    do_inspect_coin_cmd(ctx, [kwargs['coin']],
                                        print_results=False)[0],
                    parse_program(sanitize_bytes(kwargs['puzzle_reveal'])),
                    parse_program(sanitize_bytes(kwargs['solution'])),
                )
            ]
        else:
            print("Invalid arguments specified.")
    elif not kwargs or not any([kwargs[key] for key in kwargs.keys()]):
        coin_spend_objs = []
        try:
            if type(spends[0]) == str:
                coin_spend_objs = streamable_load(CoinSpend, spends)
            else:
                coin_spend_objs = spends
        except:
            print("One or more of the specified objects was not a coin spend")
    else:
        print("Invalid arguments specified.")
        return

    if print_results:
        inspect_callback(coin_spend_objs,
                         ctx,
                         id_calc=(lambda e: e.coin.name()),
                         type='CoinSpend')
    else:
        return coin_spend_objs
Esempio n. 18
0
    async def send_transaction(
        self,
        wallet_id: str,
        amount: uint64,
        address: str,
        fee: uint64 = uint64(0)) -> TransactionRecord:

        res = await self.fetch(
            "send_transaction",
            {
                "wallet_id": wallet_id,
                "amount": amount,
                "address": address,
                "fee": fee
            },
        )
        return TransactionRecord.from_json_dict(res["transaction"])
    async def add_block_record(self, header_block_record: HeaderBlockRecord,
                               block_record: BlockRecord):
        """
        Adds a block record to the database. This block record is assumed to be connected
        to the chain, but it may or may not be in the LCA path.
        """
        cached = self.block_cache.get(header_block_record.header_hash)
        if cached is not None:
            # Since write to db can fail, we remove from cache here to avoid potential inconsistency
            # Adding to cache only from reading
            self.block_cache.put(header_block_record.header_hash, None)

        if header_block_record.header.foliage_transaction_block is not None:
            timestamp = header_block_record.header.foliage_transaction_block.timestamp
        else:
            timestamp = uint64(0)
        cursor = await self.db.execute(
            "INSERT OR REPLACE INTO header_blocks VALUES(?, ?, ?, ?)",
            (
                header_block_record.header_hash.hex(),
                header_block_record.height,
                timestamp,
                bytes(header_block_record),
            ),
        )

        await cursor.close()
        cursor_2 = await self.db.execute(
            "INSERT OR REPLACE INTO block_records VALUES(?, ?, ?, ?, ?, ?, ?,?)",
            (
                header_block_record.header.header_hash.hex(),
                header_block_record.header.prev_header_hash.hex(),
                header_block_record.header.height,
                header_block_record.header.weight.to_bytes(
                    128 // 8, "big", signed=False).hex(),
                header_block_record.header.total_iters.to_bytes(
                    128 // 8, "big", signed=False).hex(),
                bytes(block_record),
                None if block_record.sub_epoch_summary_included is None else
                bytes(block_record.sub_epoch_summary_included),
                False,
            ),
        )

        await cursor_2.close()
Esempio n. 20
0
    async def get_unconfirmed_balance(self, record_list=None) -> uint64:
        confirmed = await self.get_confirmed_balance(record_list)
        unconfirmed_tx: List[
            TransactionRecord] = await self.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(
                self.wallet_info.id)
        addition_amount = 0
        removal_amount = 0

        for record in unconfirmed_tx:
            if record.type == TransactionType.INCOMING_TX:
                addition_amount += record.amount
            else:
                removal_amount += record.amount

        result = confirmed - removal_amount + addition_amount

        self.log.info(f"Unconfirmed balance for did wallet is {result}")
        return uint64(result)
Esempio n. 21
0
def calculate_cost_of_program(program: SerializedProgram,
                              npc_result: NPCResult,
                              cost_per_byte: int) -> uint64:
    """
    This function calculates the total cost of either a block or a spendbundle
    """
    total_cost = 0
    total_cost += npc_result.clvm_cost
    npc_list = npc_result.npc_list
    # Add cost of conditions
    npc: NPC
    for npc in npc_list:
        total_cost += conditions_cost(npc.condition_dict)

    # Add raw size of the program
    total_cost += len(bytes(program)) * cost_per_byte

    return uint64(total_cost)
Esempio n. 22
0
    async def create_spend_bundle_relative_chia(
            self, chia_amount: int, exclude: List[Coin]) -> SpendBundle:
        list_of_solutions = []
        utxos = None

        # If we're losing value then get coins with at least that much value
        # If we're gaining value then our amount doesn't matter
        if chia_amount < 0:
            utxos = await self.select_coins(abs(chia_amount), exclude)
        else:
            utxos = await self.select_coins(0, exclude)

        assert len(utxos) > 0

        # Calculate output amount given sum of utxos
        spend_value = sum([coin.amount for coin in utxos])
        chia_amount = spend_value + chia_amount

        # Create coin solutions for each utxo
        output_created = None
        for coin in utxos:
            puzzle = await self.puzzle_for_puzzle_hash(coin.puzzle_hash)
            if output_created is None:
                newpuzhash = await self.get_new_puzzlehash()
                primaries: List[AmountWithPuzzlehash] = [{
                    "puzzlehash":
                    newpuzhash,
                    "amount":
                    uint64(chia_amount),
                    "memos": []
                }]
                solution = self.make_solution(primaries=primaries)
                output_created = coin
            list_of_solutions.append(CoinSpend(coin, puzzle, solution))

        await self.hack_populate_secret_keys_for_coin_spends(list_of_solutions)
        spend_bundle = await sign_coin_spends(
            list_of_solutions,
            self.secret_key_store.secret_key_for_public_key,
            self.wallet_state_manager.constants.AGG_SIG_ME_ADDITIONAL_DATA,
            self.wallet_state_manager.constants.MAX_BLOCK_COST_CLVM,
        )
        return spend_bundle
Esempio n. 23
0
    async def get_pending_change_balance(self) -> uint64:
        unconfirmed_tx = await self.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(self.id())
        addition_amount = 0

        for record in unconfirmed_tx:
            our_spend = False
            for coin in record.removals:
                if await self.wallet_state_manager.does_coin_belong_to_wallet(coin, self.id()):
                    our_spend = True
                    break

            if our_spend is not True:
                continue

            for coin in record.additions:
                if await self.wallet_state_manager.does_coin_belong_to_wallet(coin, self.id()):
                    addition_amount += coin.amount

        return uint64(addition_amount)
Esempio n. 24
0
    async def join_pool(self, target_state: PoolState, fee: uint64) -> Tuple[uint64, TransactionRecord]:
        if target_state.state != FARMING_TO_POOL:
            raise ValueError(f"join_pool must be called with target_state={FARMING_TO_POOL} (FARMING_TO_POOL)")
        if self.target_state is not None:
            raise ValueError(f"Cannot join a pool while waiting for target state: {self.target_state}")
        if await self.have_unconfirmed_transaction():
            raise ValueError(
                "Cannot join pool due to unconfirmed transaction. If this is stuck, delete the unconfirmed transaction."
            )

        current_state: PoolWalletInfo = await self.get_current_state()

        total_fee = fee
        if current_state.current == target_state:
            self.target_state = None
            msg = f"Asked to change to current state. Target = {target_state}"
            self.log.info(msg)
            raise ValueError(msg)
        elif current_state.current.state in [SELF_POOLING, LEAVING_POOL]:
            total_fee = fee
        elif current_state.current.state == FARMING_TO_POOL:
            total_fee = uint64(fee * 2)

        if self.target_state is not None:
            raise ValueError(
                f"Cannot change to state {target_state} when already having target state: {self.target_state}"
            )
        PoolWallet._verify_initial_target_state(target_state)
        if current_state.current.state == LEAVING_POOL:
            history: List[Tuple[uint32, CoinSpend]] = await self.get_spend_history()
            last_height: uint32 = history[-1][0]
            if self.wallet_state_manager.get_peak().height <= last_height + current_state.current.relative_lock_height:
                raise ValueError(
                    f"Cannot join a pool until height {last_height + current_state.current.relative_lock_height}"
                )

        self.target_state = target_state
        self.next_transaction_fee = fee
        tx_record: TransactionRecord = await self.generate_travel_transaction(fee)
        await self.wallet_state_manager.add_pending_transaction(tx_record)

        return total_fee, tx_record
Esempio n. 25
0
    def validate_spend_bundle(
        self,
        spend_bundle: SpendBundle,
        now: CoinTimestamp,
        max_cost: int,
    ) -> int:
        # this should use blockchain consensus code

        coin_announcements: Set[bytes32] = set()
        puzzle_announcements: Set[bytes32] = set()

        conditions_dicts = []
        for coin_solution in spend_bundle.coin_solutions:
            err, conditions_dict, cost = conditions_dict_for_solution(
                coin_solution.puzzle_reveal, coin_solution.solution, max_cost)
            if conditions_dict is None:
                raise BadSpendBundleError(f"clvm validation failure {err}")
            conditions_dicts.append(conditions_dict)
            coin_announcements.update(
                coin_announcement_names_for_conditions_dict(
                    conditions_dict, coin_solution.coin.name()))
            puzzle_announcements.update(
                puzzle_announcement_names_for_conditions_dict(
                    conditions_dict, coin_solution.coin.puzzle_hash))

        for coin_solution, conditions_dict in zip(spend_bundle.coin_solutions,
                                                  conditions_dicts):
            prev_transaction_block_height = now.height
            timestamp = now.seconds
            coin_record = self._db[coin_solution.coin.name()]
            err = mempool_check_conditions_dict(
                coin_record,
                coin_announcements,
                puzzle_announcements,
                conditions_dict,
                uint32(prev_transaction_block_height),
                uint64(timestamp),
            )
        if err is not None:
            raise BadSpendBundleError(f"condition validation failure {err}")

        return 0
Esempio n. 26
0
    async def create_offer_for_ids(
            self,
            offer_dict: Dict[uint32, int],
            fee=uint64(0),
            validate_only: bool = False
    ) -> Tuple[Optional[Offer], TradeRecord]:
        send_dict: Dict[str, int] = {}
        for key in offer_dict:
            send_dict[str(key)] = offer_dict[key]

        res = await self.fetch("create_offer_for_ids", {
            "offer": send_dict,
            "validate_only": validate_only,
            "fee": fee
        })
        offer: Optional[Offer] = None if validate_only else Offer.from_bech32(
            res["offer"])
        offer_str: str = "" if offer is None else bytes(offer).hex()
        return offer, TradeRecord.from_json_dict_convenience(
            res["trade_record"], offer_str)
Esempio n. 27
0
 def farm_coin(
     self,
     puzzle_hash: bytes32,
     birthday: CoinTimestamp,
     amount: int = 1024,
     prefix=bytes32.fromhex("ccd5bb71183532bff220ba46c268991a00000000000000000000000000000000"),  # noqa
 ) -> Coin:
     parent = bytes32(
         [
             a | b
             for a, b in zip(
                 prefix,
                 birthday.height.to_bytes(32, "big"),
             )
         ],
     )
     # parent = birthday.height.to_bytes(32, "big")
     coin = Coin(parent, puzzle_hash, uint64(amount))
     self._add_coin_entry(coin, birthday)
     return coin
Esempio n. 28
0
    async def create(
        wallet_state_manager: Any,
        wallet: Wallet,
        launcher_coin_id: bytes32,
        block_spends: List[CoinSpend],
        block_height: uint32,
        in_transaction: bool,
        name: str = None,
    ):
        """
        This creates a new PoolWallet with only one spend: the launcher spend. The DB MUST be committed after calling
        this method.
        """
        self = PoolWallet()
        self.wallet_state_manager = wallet_state_manager

        self.wallet_info = await wallet_state_manager.user_store.create_wallet(
            "Pool wallet", WalletType.POOLING_WALLET.value, "", in_transaction=in_transaction
        )
        self.wallet_id = self.wallet_info.id
        self.standard_wallet = wallet
        self.target_state = None
        self.next_transaction_fee = uint64(0)
        self.log = logging.getLogger(name if name else __name__)

        launcher_spend: Optional[CoinSpend] = None
        for spend in block_spends:
            if spend.coin.name() == launcher_coin_id:
                launcher_spend = spend
        assert launcher_spend is not None
        await self.wallet_state_manager.pool_store.add_spend(self.wallet_id, launcher_spend, block_height)
        await self.update_pool_config(True)

        p2_puzzle_hash: bytes32 = (await self.get_current_state()).p2_singleton_puzzle_hash
        await self.wallet_state_manager.interested_store.add_interested_puzzle_hash(
            p2_puzzle_hash, self.wallet_id, True
        )

        await self.wallet_state_manager.add_new_wallet(self, self.wallet_info.id, create_puzzle_hashes=False)
        self.wallet_state_manager.set_new_peak_callback(self.wallet_id, self.new_peak)
        return self
Esempio n. 29
0
    async def new_signage_point(self, new_signage_point: farmer_protocol.NewSignagePoint):
        pool_difficulties: List[PoolDifficulty] = []
        for p2_singleton_puzzle_hash, pool_dict in self.farmer.pool_state.items():
            if pool_dict["pool_config"].pool_url == "":
                # Self pooling
                continue

            if pool_dict["current_difficulty"] is None:
                self.farmer.log.warning(
                    f"No pool specific difficulty has been set for {p2_singleton_puzzle_hash}, "
                    f"check communication with the pool, skipping this signage point, pool: "
                    f"{pool_dict['pool_config'].pool_url} "
                )
                continue
            pool_difficulties.append(
                PoolDifficulty(
                    pool_dict["current_difficulty"],
                    self.farmer.constants.POOL_SUB_SLOT_ITERS,
                    p2_singleton_puzzle_hash,
                )
            )
        message = harvester_protocol.NewSignagePointHarvester(
            new_signage_point.challenge_hash,
            new_signage_point.difficulty,
            new_signage_point.sub_slot_iters,
            new_signage_point.signage_point_index,
            new_signage_point.challenge_chain_sp,
            pool_difficulties,
        )

        msg = make_msg(ProtocolMessageTypes.new_signage_point_harvester, message)
        await self.farmer.server.send_to_all([msg], NodeType.HARVESTER)
        if new_signage_point.challenge_chain_sp not in self.farmer.sps:
            self.farmer.sps[new_signage_point.challenge_chain_sp] = []
        if new_signage_point in self.farmer.sps[new_signage_point.challenge_chain_sp]:
            self.farmer.log.debug(f"Duplicate signage point {new_signage_point.signage_point_index}")
            return

        self.farmer.sps[new_signage_point.challenge_chain_sp].append(new_signage_point)
        self.farmer.cache_add_time[new_signage_point.challenge_chain_sp] = uint64(int(time.time()))
        self.farmer.state_changed("new_signage_point", {"sp_hash": new_signage_point.challenge_chain_sp})
Esempio n. 30
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)