Esempio n. 1
0
 async def generate_eve_spend(self, coin: Coin, full_puzzle: Program, innerpuz: Program):
     assert self.did_info.origin_coin is not None
     # innerpuz solution is (mode amount message new_puzhash)
     innersol = Program.to([1, coin.amount, [], innerpuz.get_tree_hash()])
     # full solution is (lineage_proof my_amount inner_solution)
     fullsol = Program.to(
         [
             [self.did_info.origin_coin.parent_coin_info, self.did_info.origin_coin.amount],
             coin.amount,
             innersol,
         ]
     )
     list_of_solutions = [CoinSpend(coin, full_puzzle, fullsol)]
     # sign for AGG_SIG_ME
     message = (
         Program.to([innerpuz.get_tree_hash(), coin.amount, []]).get_tree_hash()
         + coin.name()
         + self.wallet_state_manager.constants.AGG_SIG_ME_ADDITIONAL_DATA
     )
     pubkey = did_wallet_puzzles.get_pubkey_from_innerpuz(innerpuz)
     record: Optional[DerivationRecord] = await self.wallet_state_manager.puzzle_store.record_for_pubkey(pubkey)
     assert record is not None
     private = master_sk_to_wallet_sk_unhardened(self.wallet_state_manager.private_key, record.index)
     signature = AugSchemeMPL.sign(private, message)
     sigs = [signature]
     aggsig = AugSchemeMPL.aggregate(sigs)
     spend_bundle = SpendBundle(list_of_solutions, aggsig)
     return spend_bundle
Esempio n. 2
0
def derive_wallet_address(
    root_path: Path,
    private_key: PrivateKey,
    index: int,
    count: int,
    prefix: Optional[str],
    non_observer_derivation: bool,
    show_hd_path: bool,
):
    """
    Generate wallet addresses using keys derived from the provided private key.
    """

    if prefix is None:
        config: Dict = load_config(root_path, "config.yaml")
        selected: str = config["selected_network"]
        prefix = config["network_overrides"]["config"][selected]["address_prefix"]
    path_indices: List[int] = [12381, 8444, 2]
    wallet_hd_path_root: str = "m/"
    for i in path_indices:
        wallet_hd_path_root += f"{i}{'n' if non_observer_derivation else ''}/"
    for i in range(index, index + count):
        if non_observer_derivation:
            sk = master_sk_to_wallet_sk(private_key, uint32(i))
        else:
            sk = master_sk_to_wallet_sk_unhardened(private_key, uint32(i))
        # Generate a wallet address using the standard p2_delegated_puzzle_or_hidden_puzzle puzzle
        # TODO: consider generating addresses using other puzzles
        address = encode_puzzle_hash(create_puzzlehash_for_pk(sk.get_g1()), prefix)
        if show_hd_path:
            print(
                f"Wallet address {i} "
                f"({wallet_hd_path_root + str(i) + ('n' if non_observer_derivation else '')}): {address}"
            )
        else:
            print(f"Wallet address {i}: {address}")
Esempio n. 3
0
    async def recovery_spend(
        self,
        coin: Coin,
        puzhash: bytes32,
        parent_innerpuzhash_amounts_for_recovery_ids: List[Tuple[bytes, bytes, int]],
        pubkey: G1Element,
        spend_bundle: SpendBundle,
    ) -> SpendBundle:
        assert self.did_info.origin_coin is not None

        # innersol is mode new_amount message new_inner_puzhash parent_innerpuzhash_amounts_for_recovery_ids pubkey recovery_list_reveal)  # noqa
        innersol: Program = Program.to(
            [
                2,
                coin.amount,
                puzhash,
                puzhash,
                parent_innerpuzhash_amounts_for_recovery_ids,
                bytes(pubkey),
                self.did_info.backup_ids,
            ]
        )
        # full solution is (parent_info my_amount solution)
        assert self.did_info.current_inner is not None
        innerpuz: Program = self.did_info.current_inner
        full_puzzle: Program = did_wallet_puzzles.create_fullpuz(
            innerpuz,
            self.did_info.origin_coin.name(),
        )
        parent_info = self.get_parent_for_coin(coin)
        assert parent_info is not None
        fullsol = Program.to(
            [
                [
                    parent_info.parent_name,
                    parent_info.inner_puzzle_hash,
                    parent_info.amount,
                ],
                coin.amount,
                innersol,
            ]
        )
        list_of_solutions = [CoinSpend(coin, full_puzzle, fullsol)]

        index = await self.wallet_state_manager.puzzle_store.index_for_pubkey(pubkey)
        if index is None:
            raise ValueError("Unknown pubkey.")
        private = master_sk_to_wallet_sk_unhardened(self.wallet_state_manager.private_key, index)
        message = bytes(puzhash)
        sigs = [AugSchemeMPL.sign(private, message)]
        for _ in spend_bundle.coin_spends:
            sigs.append(AugSchemeMPL.sign(private, message))
        aggsig = AugSchemeMPL.aggregate(sigs)
        # assert AugSchemeMPL.verify(pubkey, message, aggsig)
        if spend_bundle is None:
            spend_bundle = SpendBundle(list_of_solutions, aggsig)
        else:
            spend_bundle = spend_bundle.aggregate([spend_bundle, SpendBundle(list_of_solutions, aggsig)])

        did_record = TransactionRecord(
            confirmed_at_height=uint32(0),
            created_at_time=uint64(int(time.time())),
            to_puzzle_hash=puzhash,
            amount=uint64(coin.amount),
            fee_amount=uint64(0),
            confirmed=False,
            sent=uint32(0),
            spend_bundle=spend_bundle,
            additions=spend_bundle.additions(),
            removals=spend_bundle.removals(),
            wallet_id=self.wallet_info.id,
            sent_to=[],
            trade_id=None,
            type=uint32(TransactionType.OUTGOING_TX.value),
            name=bytes32(token_bytes()),
            memos=list(compute_memos(spend_bundle).items()),
        )
        await self.standard_wallet.push_transaction(did_record)
        new_did_info = DIDInfo(
            self.did_info.origin_coin,
            self.did_info.backup_ids,
            self.did_info.num_of_backup_ids_needed,
            self.did_info.parent_info,
            self.did_info.current_inner,
            self.did_info.temp_coin,
            self.did_info.temp_puzhash,
            self.did_info.temp_pubkey,
            True,
        )
        await self.save_info(new_did_info, True)
        return spend_bundle
Esempio n. 4
0
    async def create_attestment(
        self, recovering_coin_name: bytes32, newpuz: bytes32, pubkey: G1Element, filename=None
    ) -> SpendBundle:
        assert self.did_info.current_inner is not None
        assert self.did_info.origin_coin is not None
        coins = await self.select_coins(1)
        assert coins is not None and coins != set()
        coin = coins.pop()
        message = did_wallet_puzzles.create_recovery_message_puzzle(recovering_coin_name, newpuz, pubkey)
        innermessage = message.get_tree_hash()
        innerpuz: Program = self.did_info.current_inner
        # innerpuz solution is (mode, amount, message, new_inner_puzhash)
        messages = [(0, innermessage)]
        innersol = Program.to([1, coin.amount, messages, innerpuz.get_tree_hash()])

        # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
        full_puzzle: Program = did_wallet_puzzles.create_fullpuz(
            innerpuz,
            self.did_info.origin_coin.name(),
        )
        parent_info = self.get_parent_for_coin(coin)
        assert parent_info is not None

        fullsol = Program.to(
            [
                [
                    parent_info.parent_name,
                    parent_info.inner_puzzle_hash,
                    parent_info.amount,
                ],
                coin.amount,
                innersol,
            ]
        )
        list_of_solutions = [CoinSpend(coin, full_puzzle, fullsol)]
        message_spend = did_wallet_puzzles.create_spend_for_message(coin.name(), recovering_coin_name, newpuz, pubkey)
        message_spend_bundle = SpendBundle([message_spend], AugSchemeMPL.aggregate([]))
        # sign for AGG_SIG_ME
        to_sign = Program.to([innerpuz.get_tree_hash(), coin.amount, messages]).get_tree_hash()
        message = to_sign + coin.name() + self.wallet_state_manager.constants.AGG_SIG_ME_ADDITIONAL_DATA
        pubkey = did_wallet_puzzles.get_pubkey_from_innerpuz(innerpuz)
        index = await self.wallet_state_manager.puzzle_store.index_for_pubkey(pubkey)
        private = master_sk_to_wallet_sk_unhardened(self.wallet_state_manager.private_key, index)
        signature = AugSchemeMPL.sign(private, message)
        # assert signature.validate([signature.PkMessagePair(pubkey, message)])
        spend_bundle = SpendBundle(list_of_solutions, signature)
        did_record = TransactionRecord(
            confirmed_at_height=uint32(0),
            created_at_time=uint64(int(time.time())),
            to_puzzle_hash=coin.puzzle_hash,
            amount=uint64(coin.amount),
            fee_amount=uint64(0),
            confirmed=False,
            sent=uint32(0),
            spend_bundle=spend_bundle,
            additions=spend_bundle.additions(),
            removals=spend_bundle.removals(),
            wallet_id=self.wallet_info.id,
            sent_to=[],
            trade_id=None,
            type=uint32(TransactionType.INCOMING_TX.value),
            name=bytes32(token_bytes()),
            memos=list(compute_memos(spend_bundle).items()),
        )
        await self.standard_wallet.push_transaction(did_record)
        if filename is not None:
            f = open(filename, "w")
            f.write(self.get_my_DID())
            f.write(":")
            f.write(bytes(message_spend_bundle).hex())
            f.write(":")
            parent = coin.parent_coin_info.hex()
            innerpuzhash = self.did_info.current_inner.get_tree_hash().hex()
            amount = coin.amount
            f.write(parent)
            f.write(":")
            f.write(innerpuzhash)
            f.write(":")
            f.write(str(amount))
            f.close()
        return message_spend_bundle
Esempio n. 5
0
    async def create_exit_spend(self, puzhash: bytes32):
        assert self.did_info.current_inner is not None
        assert self.did_info.origin_coin is not None
        coins = await self.select_coins(1)
        assert coins is not None
        coin = coins.pop()
        amount = coin.amount - 1
        # innerpuz solution is (mode amount new_puzhash)
        innersol: Program = Program.to([0, amount, puzhash])
        # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
        innerpuz: Program = self.did_info.current_inner

        full_puzzle: Program = did_wallet_puzzles.create_fullpuz(
            innerpuz,
            self.did_info.origin_coin.name(),
        )
        parent_info = self.get_parent_for_coin(coin)
        assert parent_info is not None
        fullsol = Program.to(
            [
                [
                    parent_info.parent_name,
                    parent_info.inner_puzzle_hash,
                    parent_info.amount,
                ],
                coin.amount,
                innersol,
            ]
        )
        list_of_solutions = [CoinSpend(coin, full_puzzle, fullsol)]
        # sign for AGG_SIG_ME
        message = (
            Program.to([amount, puzhash]).get_tree_hash()
            + coin.name()
            + self.wallet_state_manager.constants.AGG_SIG_ME_ADDITIONAL_DATA
        )
        pubkey = did_wallet_puzzles.get_pubkey_from_innerpuz(innerpuz)
        index = await self.wallet_state_manager.puzzle_store.index_for_pubkey(pubkey)
        private = master_sk_to_wallet_sk_unhardened(self.wallet_state_manager.private_key, index)
        signature = AugSchemeMPL.sign(private, message)
        # assert signature.validate([signature.PkMessagePair(pubkey, message)])
        sigs = [signature]
        aggsig = AugSchemeMPL.aggregate(sigs)
        spend_bundle = SpendBundle(list_of_solutions, aggsig)

        did_record = TransactionRecord(
            confirmed_at_height=uint32(0),
            created_at_time=uint64(int(time.time())),
            to_puzzle_hash=puzhash,
            amount=uint64(coin.amount),
            fee_amount=uint64(0),
            confirmed=False,
            sent=uint32(0),
            spend_bundle=spend_bundle,
            additions=spend_bundle.additions(),
            removals=spend_bundle.removals(),
            wallet_id=self.wallet_info.id,
            sent_to=[],
            trade_id=None,
            type=uint32(TransactionType.OUTGOING_TX.value),
            name=bytes32(token_bytes()),
            memos=list(compute_memos(spend_bundle).items()),
        )
        await self.standard_wallet.push_transaction(did_record)
        return spend_bundle