示例#1
0
    def from_spend_bundle(cls, bundle: SpendBundle) -> "Offer":
        # Because of the `to_spend_bundle` method, we need to parse the dummy CoinSpends as `requested_payments`
        requested_payments: Dict[Optional[bytes32],
                                 List[NotarizedPayment]] = {}
        leftover_coin_spends: List[CoinSpend] = []
        for coin_spend in bundle.coin_spends:
            if coin_spend.coin.parent_coin_info == ZERO_32:
                matched, curried_args = match_cat_puzzle(
                    coin_spend.puzzle_reveal.to_program())
                if matched:
                    _, tail_hash_program, _ = curried_args
                    tail_hash: Optional[bytes32] = bytes32(
                        tail_hash_program.as_python())
                else:
                    tail_hash = None

                notarized_payments: List[NotarizedPayment] = []
                for payment_group in coin_spend.solution.to_program().as_iter(
                ):
                    nonce = bytes32(payment_group.first().as_python())
                    payment_args_list: List[Program] = payment_group.rest(
                    ).as_iter()
                    notarized_payments.extend([
                        NotarizedPayment.from_condition_and_nonce(
                            condition, nonce)
                        for condition in payment_args_list
                    ])
                requested_payments[tail_hash] = notarized_payments

            else:
                leftover_coin_spends.append(coin_spend)

        return cls(
            requested_payments,
            SpendBundle(leftover_coin_spends, bundle.aggregated_signature))
示例#2
0
    async def get_block_records_close_to_peak(
        self, blocks_n: int
    ) -> Tuple[Dict[bytes32, BlockRecord], Optional[bytes32]]:
        """
        Returns a dictionary with all blocks that have height >= peak height - blocks_n, as well as the
        peak header hash.
        """

        peak = await self.get_peak()
        if peak is None:
            return {}, None

        ret: Dict[bytes32, BlockRecord] = {}
        if self.db_wrapper.db_version == 2:

            async with self.db.execute(
                "SELECT header_hash, block_record FROM full_blocks WHERE height >= ?",
                (peak[1] - blocks_n,),
            ) as cursor:
                for row in await cursor.fetchall():
                    header_hash = bytes32(row[0])
                    ret[header_hash] = BlockRecord.from_bytes(row[1])

        else:
            formatted_str = f"SELECT header_hash, block  from block_records WHERE height >= {peak[1] - blocks_n}"
            async with self.db.execute(formatted_str) as cursor:
                for row in await cursor.fetchall():
                    header_hash = bytes32(self.maybe_from_hex(row[0]))
                    ret[header_hash] = BlockRecord.from_bytes(row[1])

        return ret, peak[0]
示例#3
0
    async def get_block_records_in_range(
        self,
        start: int,
        stop: int,
    ) -> Dict[bytes32, BlockRecord]:
        """
        Returns a dictionary with all blocks in range between start and stop
        if present.
        """

        ret: Dict[bytes32, BlockRecord] = {}
        if self.db_wrapper.db_version == 2:

            async with self.db.execute(
                "SELECT header_hash, block_record FROM full_blocks WHERE height >= ? AND height <= ?",
                (start, stop),
            ) as cursor:
                for row in await cursor.fetchall():
                    header_hash = bytes32(row[0])
                    ret[header_hash] = BlockRecord.from_bytes(row[1])

        else:

            formatted_str = f"SELECT header_hash, block from block_records WHERE height >= {start} and height <= {stop}"

            async with await self.db.execute(formatted_str) as cursor:
                for row in await cursor.fetchall():
                    header_hash = bytes32(self.maybe_from_hex(row[0]))
                    ret[header_hash] = BlockRecord.from_bytes(row[1])

        return ret
示例#4
0
    async def get_unspent_coins_for_wallet(
            self, wallet_id: int) -> Set[WalletCoinRecord]:
        """ Returns set of CoinRecords that have not been spent yet for a wallet. """
        async with self.wallet_cache_lock:
            if wallet_id in self.coin_wallet_record_cache:
                wallet_coins: Dict[
                    bytes32, WalletCoinRecord] = self.coin_wallet_record_cache[
                        wallet_id]
                return set(wallet_coins.values())

            coin_set = set()

            cursor = await self.db_connection.execute(
                "SELECT * from coin_record WHERE spent=0 and wallet_id=?",
                (wallet_id, ),
            )
            rows = await cursor.fetchall()
            await cursor.close()
            cache_dict = {}
            for row in rows:
                coin = Coin(bytes32(bytes.fromhex(row[6])),
                            bytes32(bytes.fromhex(row[5])),
                            uint64.from_bytes(row[7]))
                coin_record = WalletCoinRecord(coin, row[1], row[2],
                                               row[3], row[4],
                                               WalletType(row[8]), row[9])
                coin_set.add(coin_record)
                cache_dict[coin.name()] = coin_record

            self.coin_wallet_record_cache[wallet_id] = cache_dict
            return coin_set
示例#5
0
    async def get_coin_records_by_parent_ids(
        self,
        include_spent_coins: bool,
        parent_ids: List[bytes32],
        start_height: uint32 = uint32(0),
        end_height: uint32 = uint32((2 ** 32) - 1),
    ) -> List[CoinRecord]:
        if len(parent_ids) == 0:
            return []

        coins = set()
        parent_ids_db = tuple([pid.hex() for pid in parent_ids])
        cursor = await self.coin_record_db.execute(
            f'SELECT * from coin_record WHERE coin_parent in ({"?," * (len(parent_ids_db) - 1)}?) '
            f"AND confirmed_index>=? AND confirmed_index<? "
            f"{'' if include_spent_coins else 'AND spent=0'}",
            parent_ids_db + (start_height, end_height),
        )

        rows = await cursor.fetchall()

        await cursor.close()
        for row in rows:
            coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
            coins.add(CoinRecord(coin, row[1], row[2], row[3], row[4], row[8]))
        return list(coins)
示例#6
0
def compress_root(mystr: bytes) -> bytes32:
    assert len(mystr) == 33
    if mystr[0:1] == MIDDLE:
        return bytes32(mystr[1:])
    if mystr[0:1] == EMPTY:
        assert mystr[1:] == BLANK
        return BLANK
    return bytes32(sha256(mystr).digest()[:32])
示例#7
0
 async def get_coins_added_at_height(self, height: uint32) -> List[CoinRecord]:
     cursor = await self.coin_record_db.execute("SELECT * from coin_record WHERE confirmed_index=?", (height,))
     rows = await cursor.fetchall()
     await cursor.close()
     coins = []
     for row in rows:
         coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
         coins.append(CoinRecord(coin, row[1], row[2], row[3], row[4], row[8]))
     return coins
 async def get_coin_record(self, coin_name: bytes32) -> Optional[CoinRecord]:
     if coin_name.hex() in self.coin_record_cache:
         return self.coin_record_cache[coin_name.hex()]
     cursor = await self.coin_record_db.execute("SELECT * from coin_record WHERE coin_name=?", (coin_name.hex(),))
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
         return CoinRecord(coin, row[1], row[2], row[3], row[4], row[8])
     return None
示例#9
0
 async def get_coin_records_by_puzzle_hash(self, puzzle_hash: bytes32) -> List[WalletCoinRecord]:
     """Returns a list of all coin records with the given puzzle hash"""
     coins = set()
     cursor = await self.db_connection.execute("SELECT * from coin_record WHERE puzzle_hash=?", (puzzle_hash.hex(),))
     rows = await cursor.fetchall()
     await cursor.close()
     for row in rows:
         coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
         coins.add(WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]))
     return list(coins)
示例#10
0
    async def get_coin_record_by_coin_id(self, coin_id: bytes32) -> Optional[WalletCoinRecord]:
        """Returns a coin records with the given name, if it exists"""
        cursor = await self.db_connection.execute("SELECT * from coin_record WHERE coin_name=?", (coin_id.hex(),))
        row = await cursor.fetchone()
        await cursor.close()
        if row is None:
            return None

        coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
        coin_record = WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9])
        return coin_record
示例#11
0
 async def get_coin_record(self, coin_name: bytes32) -> Optional[WalletCoinRecord]:
     """ Returns CoinRecord with specified coin id. """
     if coin_name in self.coin_record_cache:
         return self.coin_record_cache[coin_name]
     cursor = await self.db_connection.execute("SELECT * from coin_record WHERE coin_name=?", (coin_name.hex(),))
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
         return WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9])
     return None
示例#12
0
    async def get_all_coins(self) -> Set[WalletCoinRecord]:
        """ Returns set of all CoinRecords."""
        coins = set()

        cursor = await self.db_connection.execute("SELECT * from coin_record")
        rows = await cursor.fetchall()
        await cursor.close()
        for row in rows:
            coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
            coins.add(WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]))
        return coins
示例#13
0
    async def all_non_reward_coins(self) -> List[Coin]:
        coins = set()
        cursor = await self.mempool_manager.coin_store.coin_record_db.execute(
            "SELECT * from coin_record WHERE coinbase=0 AND spent=0 ",
        )
        rows = await cursor.fetchall()

        await cursor.close()
        for row in rows:
            coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
            coins.add(coin)
        return list(coins)
示例#14
0
 async def get_coin_record(self, coin_name: bytes32) -> Optional[CoinRecord]:
     cached = self.coin_record_cache.get(coin_name)
     if cached is not None:
         return cached
     cursor = await self.coin_record_db.execute("SELECT * from coin_record WHERE coin_name=?", (coin_name.hex(),))
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7]))
         record = CoinRecord(coin, row[1], row[2], row[3], row[4], row[8])
         self.coin_record_cache.put(record.coin.name(), record)
         return record
     return None
示例#15
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))
示例#16
0
    def get_offered_coins(self) -> Dict[Optional[bytes32], List[Coin]]:
        offered_coins: Dict[Optional[bytes32], List[Coin]] = {}

        for addition in self.bundle.additions():
            # Get the parent puzzle
            parent_puzzle: Program = list(
                filter(lambda cs: cs.coin.name() == addition.parent_coin_info,
                       self.bundle.coin_spends))[0].puzzle_reveal.to_program()

            # Determine it's TAIL (or lack of)
            matched, curried_args = match_cat_puzzle(parent_puzzle)
            tail_hash: Optional[bytes32] = None
            if matched:
                _, tail_hash_program, _ = curried_args
                tail_hash = bytes32(tail_hash_program.as_python())
                offer_ph: bytes32 = construct_cat_puzzle(
                    CAT_MOD, tail_hash, OFFER_MOD).get_tree_hash()
            else:
                tail_hash = None
                offer_ph = OFFER_MOD.get_tree_hash()

            # Check if the puzzle_hash matches the hypothetical `settlement_payments` puzzle hash
            if addition.puzzle_hash == offer_ph:
                if tail_hash in offered_coins:
                    offered_coins[tail_hash].append(addition)
                else:
                    offered_coins[tail_hash] = [addition]

        return offered_coins
示例#17
0
    async def get_block_records_close_to_peak(
            self, blocks_n: int
    ) -> Tuple[Dict[bytes32, BlockRecord], Optional[bytes32]]:
        """
        Returns a dictionary with all blocks, as well as the header hash of the peak,
        if present.
        """

        res = await self.db.execute(
            "SELECT header_hash, height from block_records WHERE is_peak = 1")
        row = await res.fetchone()
        await res.close()
        if row is None:
            return {}, None
        header_hash_bytes, peak_height = row
        peak: bytes32 = bytes32(bytes.fromhex(header_hash_bytes))

        formatted_str = f"SELECT header_hash, block from block_records WHERE height >= {peak_height - blocks_n}"
        cursor = await self.db.execute(formatted_str)
        rows = await cursor.fetchall()
        await cursor.close()
        ret: Dict[bytes32, BlockRecord] = {}
        for row in rows:
            header_hash_bytes, block_record_bytes = row
            header_hash = bytes.fromhex(header_hash_bytes)
            ret[header_hash] = BlockRecord.from_bytes(block_record_bytes)
        return ret, peak
示例#18
0
    async def get_block_records_by_hash(self, header_hashes: List[bytes32]):
        """
        Returns a list of Block Records, ordered by the same order in which header_hashes are passed in.
        Throws an exception if the blocks are not present
        """
        if len(header_hashes) == 0:
            return []

        all_blocks: Dict[bytes32, BlockRecord] = {}
        if self.db_wrapper.db_version == 2:
            async with self.db.execute(
                "SELECT header_hash,block_record FROM full_blocks "
                f'WHERE header_hash in ({"?," * (len(header_hashes) - 1)}?)',
                tuple(header_hashes),
            ) as cursor:
                for row in await cursor.fetchall():
                    header_hash = bytes32(row[0])
                    all_blocks[header_hash] = BlockRecord.from_bytes(row[1])
        else:
            formatted_str = f'SELECT block from block_records WHERE header_hash in ({"?," * (len(header_hashes) - 1)}?)'
            async with self.db.execute(formatted_str, tuple([hh.hex() for hh in header_hashes])) as cursor:
                for row in await cursor.fetchall():
                    block_rec: BlockRecord = BlockRecord.from_bytes(row[0])
                    all_blocks[block_rec.header_hash] = block_rec

        ret: List[BlockRecord] = []
        for hh in header_hashes:
            if hh not in all_blocks:
                raise ValueError(f"Header hash {hh} not in the blockchain")
            ret.append(all_blocks[hh])
        return ret
示例#19
0
    async def create_wallet_for_cat(wallet_state_manager: Any,
                                    wallet: Wallet,
                                    limitations_program_hash_hex: str,
                                    name="CAT WALLET") -> CATWallet:
        self = CATWallet()
        self.cost_of_single_tx = None
        self.standard_wallet = wallet
        self.log = logging.getLogger(__name__)

        for id, wallet in wallet_state_manager.wallets.items():
            if wallet.type() == CATWallet.type():
                if wallet.get_asset_id(
                ) == limitations_program_hash_hex:  # type: ignore
                    self.log.warning(
                        "Not creating wallet for already existing CAT wallet")
                    raise ValueError("Wallet already exists")

        self.wallet_state_manager = wallet_state_manager
        if limitations_program_hash_hex in DEFAULT_CATS:
            cat_info = DEFAULT_CATS[limitations_program_hash_hex]
            name = cat_info["name"]

        limitations_program_hash = bytes32(
            hexstr_to_bytes(limitations_program_hash_hex))
        self.cat_info = CATInfo(limitations_program_hash, None, [])
        info_as_string = bytes(self.cat_info).hex()
        self.wallet_info = await wallet_state_manager.user_store.create_wallet(
            name, WalletType.CAT, info_as_string)
        if self.wallet_info is None:
            raise Exception("wallet_info is None")

        await self.wallet_state_manager.add_new_wallet(self, self.id())
        return self
示例#20
0
 def get_quality_string(self, plot_id: bytes32) -> Optional[bytes32]:
     quality_str = Verifier().validate_proof(plot_id, self.size,
                                             self.challenge,
                                             bytes(self.proof))
     if not quality_str:
         return None
     return bytes32(quality_str)
示例#21
0
def decode_puzzle_hash(address: str) -> bytes32:
    hrpgot, data = bech32_decode(address)
    if data is None:
        raise ValueError("Invalid Address")
    decoded = convertbits(data, 5, 8, False)
    decoded_bytes = bytes32(decoded)
    return decoded_bytes
示例#22
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)
示例#23
0
    async def get_pay_to_singleton_phs(self) -> Set[bytes32]:
        cursor = await self.connection.execute("SELECT p2_singleton_puzzle_hash from farmer")
        rows = await cursor.fetchall()

        all_phs: Set[bytes32] = set()
        for row in rows:
            all_phs.add(bytes32(bytes.fromhex(row[0])))
        return all_phs
示例#24
0
 async def get_pool_login_link(self, request: Dict) -> Dict:
     launcher_id: bytes32 = bytes32(hexstr_to_bytes(request["launcher_id"]))
     login_link: Optional[str] = await self.service.generate_login_link(
         launcher_id)
     if login_link is None:
         raise ValueError(
             f"Failed to generate login link for {launcher_id.hex()}")
     return {"login_link": login_link}
示例#25
0
 def from_condition(cls, condition: Program) -> "Payment":
     python_condition: List = condition.as_python()
     puzzle_hash, amount = python_condition[1:3]
     memos: List[bytes] = []
     if len(python_condition) > 3:
         memos = python_condition[3]
     return cls(bytes32(puzzle_hash), uint64(int.from_bytes(amount, "big")),
                memos)
示例#26
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
def mempool_assert_announcement(condition: ConditionWithArgs, announcements: Set[bytes32]) -> Optional[Err]:
    """
    Check if an announcement is included in the list of announcements
    """
    announcement_hash = bytes32(condition.vars[0])
    if announcement_hash not in announcements:
        return Err.ASSERT_ANNOUNCE_CONSUMED_FAILED

    return None
示例#28
0
    async def get_peak(self) -> Optional[Tuple[bytes32, uint32]]:

        if self.db_wrapper.db_version == 2:
            async with self.db.execute("SELECT hash FROM current_peak WHERE key = 0") as cursor:
                peak_row = await cursor.fetchone()
            if peak_row is None:
                return None
            async with self.db.execute("SELECT height FROM full_blocks WHERE header_hash=?", (peak_row[0],)) as cursor:
                peak_height = await cursor.fetchone()
            if peak_height is None:
                return None
            return bytes32(peak_row[0]), uint32(peak_height[0])
        else:
            async with self.db.execute("SELECT header_hash, height from block_records WHERE is_peak = 1") as cursor:
                peak_row = await cursor.fetchone()
            if peak_row is None:
                return None
            return bytes32(bytes.fromhex(peak_row[0])), uint32(peak_row[1])
示例#29
0
 def my_id(self) -> bytes32:
     """If node has public cert use that one for id, if not use private."""
     if self.p2p_crt_path is not None:
         pem_cert = x509.load_pem_x509_certificate(self.p2p_crt_path.read_bytes(), default_backend())
     else:
         pem_cert = x509.load_pem_x509_certificate(self._private_cert_path.read_bytes(), default_backend())
     der_cert_bytes = pem_cert.public_bytes(encoding=serialization.Encoding.DER)
     der_cert = x509.load_der_x509_certificate(der_cert_bytes, default_backend())
     return bytes32(der_cert.fingerprint(hashes.SHA256()))
示例#30
0
def created_outputs_for_conditions_dict(
    conditions_dict: Dict[ConditionOpcode, List[ConditionWithArgs]],
    input_coin_name: bytes32,
) -> List[Coin]:
    output_coins = []
    for cvp in conditions_dict.get(ConditionOpcode.CREATE_COIN, []):
        puzzle_hash, amount_bin = cvp.vars[0], cvp.vars[1]
        amount = int_from_bytes(amount_bin)
        coin = Coin(input_coin_name, bytes32(puzzle_hash), uint64(amount))
        output_coins.append(coin)
    return output_coins