def solution_for_rl(
    my_parent_id: bytes32,
    my_puzzlehash: bytes32,
    my_amount: uint64,
    out_puzzlehash: bytes32,
    out_amount: uint64,
    my_parent_parent_id: bytes32,
    parent_amount: uint64,
    interval,
    limit,
    fee,
):
    """
    Solution is (1 my_parent_id, my_puzzlehash, my_amount, outgoing_puzzle_hash, outgoing_amount,
    min_block_time, parent_parent_id, parent_amount, fee)
    min block time = Math.ceil((new_amount * self.interval) / self.limit)
    """

    min_block_count = math.ceil((out_amount * interval) / limit)
    solution = sexp(
        1,
        "0x" + my_parent_id.hex(),
        "0x" + my_puzzlehash.hex(),
        my_amount,
        "0x" + out_puzzlehash.hex(),
        out_amount,
        min_block_count,
        "0x" + my_parent_parent_id.hex(),
        parent_amount,
        fee,
    )
    return Program.to(binutils.assemble(solution))
 async def get_unspent_coins(
     self, puzzle_hash: bytes32, header_hash: Optional[bytes32] = None
 ) -> List:
     if header_hash is not None:
         d = {"puzzle_hash": puzzle_hash.hex(), "header_hash": header_hash.hex()}
     else:
         d = {"puzzle_hash": puzzle_hash.hex()}
     return [
         CoinRecord.from_json_dict(coin)
         for coin in ((await self.fetch("get_unspent_coins", d))["coin_records"])
     ]
예제 #3
0
 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])), row[7])
         return CoinRecord(coin, row[1], row[2], row[3], row[4], row[8])
     return None
 async def get_network_space(
         self, newer_block_header_hash: bytes32,
         older_block_header_hash: bytes32) -> Optional[uint64]:
     try:
         network_space_bytes_estimate = await self.fetch(
             "get_network_space",
             {
                 "newer_block_header_hash": newer_block_header_hash.hex(),
                 "older_block_header_hash": older_block_header_hash.hex(),
             },
         )
     except Exception:
         return None
     return network_space_bytes_estimate["space"]
예제 #5
0
 async def get_coin_record(
         self, coin_name: bytes32) -> Optional[WalletCoinRecord]:
     """ Returns CoinRecord with specified coin id. """
     if coin_name.hex() in self.coin_record_cache:
         return self.coin_record_cache[coin_name.hex()]
     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])), row[7])
         return WalletCoinRecord(coin, row[1], row[2], row[3], row[4],
                                 WalletType(row[8]), row[9])
     return None
예제 #6
0
 async def get_transaction_record(
         self, id: bytes32) -> Optional[TransactionRecord]:
     """
     Checks DB and cache for TransactionRecord with id: id and returns it.
     """
     if id.hex() in self.tx_record_cache:
         return self.tx_record_cache[id.hex()]
     cursor = await self.db_connection.execute(
         "SELECT * from transaction_record WHERE bundle_id=?", (id.hex(), ))
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         record = TransactionRecord.from_bytes(row[0])
         return record
     return None
예제 #7
0
 async def get_block_record(self, header_hash: bytes32) -> BlockRecord:
     cursor = await self.db_connection.execute(
         "SELECT * from block_records WHERE header_hash=?", (header_hash.hex(),)
     )
     row = await cursor.fetchone()
     await cursor.close()
     return BlockRecord.from_bytes(row[3])
예제 #8
0
 async def add_block_to_path(self, header_hash: bytes32) -> None:
     cursor = await self.db_connection.execute(
         "UPDATE block_records SET in_lca_path=1 WHERE header_hash=?",
         (header_hash.hex(),),
     )
     await cursor.close()
     await self.db_connection.commit()
예제 #9
0
 async def get_block(self, header_hash: bytes32) -> Optional[FullBlock]:
     cursor = await self.db.execute(
         "SELECT * from blocks WHERE header_hash=?", (header_hash.hex(), ))
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         return FullBlock.from_bytes(row[2])
     return None
예제 #10
0
 async def set_lca(self, header_hash: bytes32) -> None:
     cursor_1 = await self.db.execute("UPDATE headers SET is_lca=0")
     await cursor_1.close()
     cursor_2 = await self.db.execute(
         "UPDATE headers SET is_lca=1 WHERE header_hash=?",
         (header_hash.hex(), ))
     await cursor_2.close()
     await self.db.commit()
예제 #11
0
 async def set_peak(self, header_hash: bytes32) -> None:
     cursor_1 = await self.db.execute("UPDATE sub_block_records SET is_peak=0 WHERE is_peak=1")
     await cursor_1.close()
     cursor_2 = await self.db.execute(
         "UPDATE sub_block_records SET is_peak=1 WHERE header_hash=?",
         (header_hash.hex(),),
     )
     await cursor_2.close()
     await self.db.commit()
예제 #12
0
 async def get_coin_record(self,
                           coin_name: bytes32,
                           header: Header = None) -> Optional[CoinRecord]:
     if header is not None and header.header_hash in self.head_diffs:
         diff_store = self.head_diffs[header.header_hash]
         if coin_name.hex() in diff_store.diffs:
             return diff_store.diffs[coin_name.hex()]
     if coin_name.hex() in self.lca_coin_records:
         return self.lca_coin_records[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])), row[7])
         return CoinRecord(coin, row[1], row[2], row[3], row[4])
     return None
예제 #13
0
 async def get_sub_block_record(self, header_hash: bytes32) -> Optional[SubBlockRecord]:
     cursor = await self.db.execute(
         "SELECT sub_block from sub_block_records WHERE header_hash=?",
         (header_hash.hex(),),
     )
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         return SubBlockRecord.from_bytes(row[0])
     return None
예제 #14
0
 async def get_transaction(self, wallet_id: str,
                           transaction_id: bytes32) -> TransactionRecord:
     res = await self.fetch(
         "get_transaction",
         {
             "walled_id": wallet_id,
             "transaction_id": transaction_id.hex()
         },
     )
     return TransactionRecord.from_json_dict(res["transaction"])
예제 #15
0
def rl_puzzle_for_pk(
    pubkey: bytes,
    rate_amount: uint64,
    interval_time: uint64,
    origin_id: bytes32,
    clawback_pk: bytes,
):
    """
        Solution to this puzzle must be in format:
        (1 my_parent_id, my_puzzlehash, my_amount, outgoing_puzzle_hash, outgoing_amount,
         min_block_time, parent_parent_id, parent_amount)
        RATE LIMIT LOGIC:
        M - chia_per_interval
        N - interval_blocks
        V - amount being spent
        MIN_BLOCK_AGE = V / (M / N)
        if not (min_block_age * M >=  V * N) do X (raise)
        ASSERT_COIN_BLOCK_AGE_EXCEEDS min_block_age
    """

    hex_pk = pubkey.hex()
    clawback_pk_str = clawback_pk.hex()
    origin_id = origin_id.hex()

    opcode_aggsig = ConditionOpcode.AGG_SIG.hex()
    opcode_coin_block_age = ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS.hex()
    opcode_create = ConditionOpcode.CREATE_COIN.hex()
    opcode_myid = ConditionOpcode.ASSERT_MY_COIN_ID.hex()

    TEMPLATE_MY_PARENT_ID = "(sha256 (f (r (r (r (r (r (r (a)))))))) (f (r (a))) (f (r (r (r (r (r (r (r (a))))))))))"
    TEMPLATE_SINGLETON_RL = f'((c (i (i (= {TEMPLATE_MY_PARENT_ID} (f (a))) (q 1) (= (f (a)) (q 0x{origin_id}))) (q ()) (q (x (q "Parent doesnt satisfy RL conditions")))) (a)))'  # noqa: E501
    TEMPLATE_BLOCK_AGE = f'((c (i (i (= (* (f (r (r (r (r (r (a))))))) (q {rate_amount})) (* (f (r (r (r (r (a)))))) (q {interval_time}))) (q 1) (q (> (* (f (r (r (r (r (r (a))))))) (q {rate_amount})) (* (f (r (r (r (r (a))))))) (q {interval_time})))) (q (c (q 0x{opcode_coin_block_age}) (c (f (r (r (r (r (r (a))))))) (q ())))) (q (x (q "wrong min block time")))) (a) ))'  # noqa: E501
    TEMPLATE_MY_ID = f"(c (q 0x{opcode_myid}) (c (sha256 (f (a)) (f (r (a))) (f (r (r (a))))) (q ())))"  # noqa: E501
    CREATE_CHANGE = f"(c (q 0x{opcode_create}) (c (f (r (a))) (c (- (f (r (r (a)))) (f (r (r (r (r (a))))))) (q ()))))"  # noqa: E501
    CREATE_NEW_COIN = f"(c (q 0x{opcode_create}) (c (f (r (r (r (a))))) (c (f (r (r (r (r (a)))))) (q ()))))"  # noqa: E501
    RATE_LIMIT_PUZZLE = f"(c {TEMPLATE_SINGLETON_RL} (c {TEMPLATE_BLOCK_AGE} (c {CREATE_CHANGE} (c {TEMPLATE_MY_ID} (c {CREATE_NEW_COIN} (q ()))))))"  # noqa: E501

    TEMPLATE_MY_PARENT_ID_2 = "(sha256 (f (r (r (r (r (r (r (r (r (a)))))))))) (f (r (a))) (f (r (r (r (r (r (r (r (a))))))))))"  # noqa: E501
    TEMPLATE_SINGLETON_RL_2 = f'((c (i (i (= {TEMPLATE_MY_PARENT_ID_2} (f (r (r (r (r (r (a)))))))) (q 1) (= (f (r (r (r (r (r (a))))))) (q 0x{origin_id}))) (q (c (q 1) (q ()))) (q (x (q "Parent doesnt satisfy RL conditions")))) (a)))'  # noqa: E501
    CREATE_CONSOLIDATED = f"(c (q 0x{opcode_create}) (c (f (r (a))) (c (+ (f (r (r (r (r (a)))))) (f (r (r (r (r (r (r (a))))))))) (q ()))))"  # noqa: E501
    MODE_TWO_ME_STRING = f"(c (q 0x{opcode_myid}) (c (sha256 (f (r (r (r (r (r (a))))))) (f (r (a))) (f (r (r (r (r (r (r (a))))))))) (q ())))"  # noqa: E501
    CREATE_LOCK = f"(c (q 0x{opcode_create}) (c (sha256tree (c (q 7) (c (c (q 5) (c (c (q 1) (c (sha256 (f (r (r (a)))) (f (r (r (r (a))))) (f (r (r (r (r (a))))))) (q ()))) (c (q (q ())) (q ())))) (q ())))) (c (q 0) (q ()))))"  # noqa: E501

    MODE_TWO = f"(c {TEMPLATE_SINGLETON_RL_2} (c {MODE_TWO_ME_STRING} (c {CREATE_LOCK} (c {CREATE_CONSOLIDATED} (q ())))))"  # noqa: E501

    AGGSIG_ENTIRE_SOLUTION = (
        f"(c (q 0x{opcode_aggsig}) (c (q 0x{hex_pk}) (c (sha256tree (a)) (q ()))))"
    )

    WHOLE_PUZZLE = f"(c {AGGSIG_ENTIRE_SOLUTION} ((c (i (= (f (a)) (q 1)) (q ((c (q {RATE_LIMIT_PUZZLE}) (r (a))))) (q {MODE_TWO})) (a))) (q ()))"  # noqa: E501
    CLAWBACK = f"(c (c (q 0x{opcode_aggsig}) (c (q 0x{clawback_pk_str}) (c (sha256tree (a)) (q ())))) (r (a)))"
    WHOLE_PUZZLE_WITH_CLAWBACK = (
        f"((c (i (= (f (a)) (q 3)) (q {CLAWBACK}) (q {WHOLE_PUZZLE})) (a)))"
    )
    return Program(binutils.assemble(WHOLE_PUZZLE_WITH_CLAWBACK))
예제 #16
0
 async def get_block_record(self, header_hash: bytes32) -> Optional[BlockRecord]:
     """Gets a block record from the database, if present"""
     cursor = await self.db_connection.execute(
         "SELECT * from block_records WHERE header_hash=?", (header_hash.hex(),)
     )
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         return BlockRecord.from_bytes(row[3])
     else:
         return None
예제 #17
0
    async def puzzle_hash_exists(self, puzzle_hash: bytes32) -> bool:
        """
        Checks if passed puzzle_hash is present in the db.
        """

        cursor = await self.db_connection.execute(
            "SELECT * from derivation_paths WHERE puzzle_hash=?",
            (puzzle_hash.hex(), ))
        row = await cursor.fetchone()
        await cursor.close()

        return row is not None
예제 #18
0
 async def get_full_block(self,
                          header_hash: bytes32) -> Optional[FullBlock]:
     cached = self.block_cache.get(header_hash)
     if cached is not None:
         return cached
     cursor = await self.db.execute(
         "SELECT block from full_blocks WHERE header_hash=?",
         (header_hash.hex(), ))
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         return FullBlock.from_bytes(row[0])
     return None
예제 #19
0
 async def get_header_block_record(
         self, header_hash: bytes32) -> Optional[HeaderBlockRecord]:
     """Gets a block record from the database, if present"""
     cursor = await self.db.execute(
         "SELECT block from header_blocks WHERE header_hash=?",
         (header_hash.hex(), ))
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         hbr = HeaderBlockRecord.from_bytes(row[0])
         return hbr
     else:
         return None
예제 #20
0
 async def get_trade_record(self,
                            trade_id: bytes32) -> Optional[TradeRecord]:
     """
     Checks DB for TradeRecord with id: id and returns it.
     """
     cursor = await self.db_connection.execute(
         "SELECT * from trade_records WHERE trade_id=?", (trade_id.hex(), ))
     row = await cursor.fetchone()
     await cursor.close()
     if row is not None:
         record = TradeRecord.from_bytes(row[0])
         return record
     return None
예제 #21
0
    async def get_coin_records_by_puzzle_hash(
            self, puzzle_hash: bytes32) -> List[CoinRecord]:
        coins = set()
        cursor = await self.coin_record_db.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])), row[7])
            coins.add(CoinRecord(coin, row[1], row[2], row[3], row[4], row[8]))
        return list(coins)
예제 #22
0
 async def is_transaction_in_mempool(api, tx_id: bytes32) -> bool:
     try:
         val = await api.get_transaction(
             {"wallet_id": user_wallet_id, "transaction_id": tx_id.hex()}
         )
     except ValueError:
         return False
     for _, mis, _ in val["transaction"].sent_to:
         if (
             MempoolInclusionStatus(mis) == MempoolInclusionStatus.SUCCESS
             or MempoolInclusionStatus(mis) == MempoolInclusionStatus.PENDING
         ):
             return True
     return False
예제 #23
0
    async def get_coin_record_by_coin_id(
            self, coin_id: bytes32) -> Optional[WalletCoinRecord]:
        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])), row[7])
        coin_record = WalletCoinRecord(coin, row[1], row[2], row[3], row[4],
                                       WalletType(row[8]), row[9])
        return coin_record
    async def index_for_puzzle_hash(self, puzzle_hash: bytes32) -> Optional[uint32]:
        """
        Returns the derivation path for the puzzle_hash.
        Returns None if not present.
        """
        cursor = await self.db_connection.execute(
            "SELECT * from derivation_paths WHERE puzzle_hash=?", (puzzle_hash.hex(),)
        )
        row = await cursor.fetchone()
        await cursor.close()

        if row is not None:
            return uint32(row[0])

        return None
 async def get_additions_and_removals(
         self,
         header_hash: bytes32) -> Tuple[List[CoinRecord], List[CoinRecord]]:
     try:
         response = await self.fetch("get_additions_and_removals",
                                     {"header_hash": header_hash.hex()})
     except Exception:
         return [], []
     removals = []
     additions = []
     for coin_record in response["removals"]:
         removals.append(CoinRecord.from_json_dict(coin_record))
     for coin_record in response["additions"]:
         additions.append(CoinRecord.from_json_dict(coin_record))
     return additions, removals
예제 #26
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])), row[7])
         coins.add(
             WalletCoinRecord(coin, row[1], row[2], row[3], row[4],
                              WalletType(row[8]), row[9]))
     return list(coins)
예제 #27
0
    async def wallet_info_for_puzzle_hash(
            self, puzzle_hash: bytes32) -> Optional[Tuple[uint32, WalletType]]:
        """
        Returns the derivation path for the puzzle_hash.
        Returns None if not present.
        """

        cursor = await self.db_connection.execute(
            "SELECT * from derivation_paths WHERE puzzle_hash=?",
            (puzzle_hash.hex(), ))
        row = await cursor.fetchone()
        await cursor.close()

        if row is not None:
            return row[4], WalletType(row[3])

        return None
예제 #28
0
 async def get_coin_records_by_puzzle_hash(
         self,
         puzzle_hash: bytes32,
         header: Header = None) -> List[CoinRecord]:
     coins = set()
     if header is not None and header.header_hash in self.head_diffs:
         diff_store = self.head_diffs[header.header_hash]
         for _, record in diff_store.diffs.items():
             if record.coin.puzzle_hash == puzzle_hash:
                 coins.add(record)
     cursor = await self.coin_record_db.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])), row[7])
         coins.add(CoinRecord(coin, row[1], row[2], row[3], row[4]))
     return list(coins)
예제 #29
0
 async def inner_puzzle_for_cc_puzzle(self, cc_hash: bytes32) -> Program:
     record: DerivationRecord = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(
         cc_hash.hex())
     inner_puzzle: Program = self.standard_wallet.puzzle_for_pk(
         bytes(record.pubkey))
     return inner_puzzle
예제 #30
0
 async def close_connection(self, node_id: bytes32) -> Dict:
     return await self.fetch("close_connection", {"node_id": node_id.hex()})