Example #1
0
    async def subadress_outs(self, tx, change_idx=None):
        change_idx = await self.find_change_idx(tx, change_idx)

        for ix, ox in enumerate(tx.splitted_dsts):
            if change_idx is not None and ix == change_idx:
                continue
            # if ox.is_subaddress:
            #     continue

            spkey = bytes(ox.addr.m_spend_public_key)
            orig_keys = self.dest_keys
            orig_idx = self.dest_sub_major, 0

            if spkey in self.cur_subs:
                orig_keys = self.cur_keys
                orig_idx = self.cur_subs[spkey]
                logger.debug('Out %d, in cur subs, idx: %s' % (ix, orig_idx))

            elif spkey in self.dest_subs:
                orig_idx = self.dest_subs[spkey]
                logger.debug('Out %d, in dst subs, idx: %s' % (ix, orig_idx))

            naddr = monero.generate_sub_address_keys(orig_keys.view_key_private, orig_keys.spend_key_public,
                                                     orig_idx[0], ix+1)

            ox.addr.m_spend_public_key = crypto.encodepoint(naddr[0])
            ox.addr.m_view_public_key = crypto.encodepoint(naddr[1])
            ox.is_subaddress = True

        return change_idx
Example #2
0
 async def get_subaddress(self):
     index = self._fetch(8)
     major, minor = self._idx_parse(index)
     D, C = monero.generate_sub_address_keys(self.a, self.B, major, minor)
     self._insert(crypto.encodepoint(C))
     self._insert(crypto.encodepoint(D))
     return SW_OK
Example #3
0
 async def primary_change_address(self, key, account):
     D, C = monero.generate_sub_address_keys(
         key.view_key_private,
         crypto.scalarmult_base(key.spend_key_private),
         account,
         0,
     )
     return misc.StdObj(
         view_public_key=crypto.encodepoint(C),
         spend_public_key=crypto.encodepoint(D),
     )
Example #4
0
def gen_sub_address(sd, net_type, major_max, minor_max):
    for major in range(major_max):
        for minor in range(minor_max):
            if major == 0 and minor == 0:
                continue

            D, C = monero.generate_sub_address_keys(sd.view_sec, sd.spend_pub,
                                                    major, minor)
            addr = encode_addr(
                net_version(net_type, is_subaddr=True),
                crypto.encodepoint(D),
                crypto.encodepoint(C),
            )
            yield major, minor, addr
Example #5
0
    async def gen_output(self,
                         value=1,
                         dest=None,
                         sub_major=0,
                         sub_minor=0,
                         payment_id=None):
        dest = dest if dest is not None else (
            self.prng.choice(self.dest_keys) if isinstance(
                self.dest_keys, list) else self.dest_keys)
        is_sub = sub_major != 0 or sub_minor != 0
        if is_sub and payment_id is not None:
            raise ValueError("Integrated cannot be subaddress")

        KS, KV = monero.generate_sub_address_keys(dest.view_key_private,
                                                  dest.spend_key_public,
                                                  sub_major, sub_minor)
        pubaddr = AccountPublicAddress(
            m_spend_public_key=crypto.encodepoint(KS),
            m_view_public_key=crypto.encodepoint(KV),
        )

        pub2 = addr.PubAddress(
            pubaddr.m_spend_public_key,
            pubaddr.m_view_public_key,
        )

        tde = TxDestinationEntry(
            amount=value,
            addr=pubaddr,
            is_subaddress=is_sub,
            original=addr.public_addr_encode(pub2, is_sub, self.nettype,
                                             payment_id),
            is_integrated=payment_id is not None,
        )

        tdextra = DestInfo(dest, sub_major, sub_minor, payment_id)
        self.outputs.append(tde)
        self.outputs_extra.append(tdextra)
        return self
Example #6
0
    async def gen_input(self,
                        value=1,
                        sub_major=None,
                        sub_minor=0,
                        additionals=False):
        creds = self.src_keys
        r = self.random_scalar()
        R = crypto.scalarmult_base(r)
        additional_keys = []
        Additional = None
        sub_major = sub_major if sub_major is not None else self.account_idx
        is_sub = sub_major != 0 or sub_minor != 0

        if sub_major != self.account_idx:
            logger.warning(
                "Generating input with different major subindex, cannot be spent in the resulting "
                "transaction")

        kssec = monero.get_subaddress_secret_key(creds.view_key_private,
                                                 major=sub_major,
                                                 minor=sub_minor)
        kssub = crypto.sc_add(
            kssec,
            creds.spend_key_private) if is_sub else creds.spend_key_private
        kvsub = crypto.sc_mul(creds.view_key_private,
                              kssub) if is_sub else creds.view_key_private
        KSSUB, KVSUB = monero.generate_sub_address_keys(
            creds.view_key_private, creds.spend_key_public, sub_major,
            sub_minor)

        if not crypto.point_eq(KSSUB, crypto.scalarmult_base(kssub)):
            raise ValueError("Invariant error")

        oidx = self.prng.randint(0, 12)
        additionals_cnt = self.prng.randint(oidx + 1, 2 * oidx + 1)
        deriv = crypto.generate_key_derivation(KVSUB, r)
        kout = crypto.derive_secret_key(deriv, oidx, kssub)
        KOUT = crypto.derive_public_key(deriv, oidx, KSSUB)
        if not crypto.point_eq(KOUT, crypto.scalarmult_base(kout)):
            raise ValueError("Invariant error")

        if additionals:
            if is_sub:
                Additional = crypto.scalarmult(KSSUB, r)
            else:
                Additional = crypto.scalarmult_base(r)
        else:
            if is_sub:
                R = crypto.scalarmult(KSSUB, r)

        amnt = crypto.sc_init(value)
        msk = self.random_scalar()  # commitment mask
        C = crypto.add_keys2(msk, amnt, crypto.xmr_H())

        ring = []
        for i in range(self.ring_size - 1):
            tk = CtKey(
                dest=crypto.encodepoint(self.random_pub()),
                mask=crypto.encodepoint(self.random_pub()),
            )
            ring.append(tk)

        index = self.prng.randint(0, len(ring))
        ring.insert(
            index,
            CtKey(dest=crypto.encodepoint(KOUT), mask=crypto.encodepoint(C)))
        if additionals:
            additional_keys = [
                self.random_pub() for _ in range(additionals_cnt)
            ]
            additional_keys[oidx] = Additional

        src = TxSourceEntry()
        src.outputs = [(self.random_glob_idx(), x) for x in ring]
        src.real_output = index
        src.real_out_tx_key = crypto.encodepoint(R)
        src.real_out_additional_tx_keys = [
            crypto.encodepoint(x) for x in additional_keys
        ]
        src.real_output_in_tx_index = oidx
        src.amount = value
        src.rct = True
        src.mask = crypto.encodeint(msk)
        src.multisig_kLRki = MultisigKLRki(K=crypto.ZERO,
                                           L=crypto.ZERO,
                                           R=crypto.ZERO,
                                           ki=crypto.ZERO)

        td = TransferDetails()
        td.m_internal_output_index = oidx
        td.m_global_output_index = src.outputs[index][0]
        td.m_mask = src.mask
        td.m_amount = value
        td.m_subaddr_index = SubaddressIndex(major=sub_major, minor=sub_minor)
        td.m_rct = True
        td.m_txid = self.random_bytes(32)
        td.m_block_height = self.prng.randint(0, 0xFFFF)
        td.m_spent = False
        td.m_spent_height = 0
        td.m_key_image_known = True
        td.m_key_image_requested = False
        td.m_key_image_partial = False
        td.m_multisig_k = []
        td.m_multisig_info = []
        td.m_uses = []
        td.m_pk_index = 0
        td.m_tx = self.gen_tx_prefix(self.prng.randint(1, 10), additionals_cnt)
        td.m_tx.vout[oidx].target.key = crypto.encodepoint(KOUT)

        extras = []
        extras.append(TxExtraNonce(nonce=self.random_bytes(8)))
        extras.append(TxExtraPubKey(pub_key=src.real_out_tx_key))
        if src.real_out_additional_tx_keys:
            extras.append(
                TxExtraAdditionalPubKeys(data=src.real_out_additional_tx_keys))
        td.m_tx.extra = await self.dump_extra_fields(extras)

        tmpsubs = {}
        monero.compute_subaddresses(creds, sub_major, [sub_minor], tmpsubs)
        xi, ki, rderiv = self.check_input(src, creds, tmpsubs)
        if not crypto.sc_eq(xi, kout):
            raise ValueError("Invariant error")

        td.m_key_image = crypto.encodepoint(ki)

        self.sources.append(src)
        self.selected_transfers.append(len(self.transfers))
        self.transfers.append(td)
        self.sources_creds.append(creds)

        if not crypto.point_eq(
                crypto.decodepoint(src.outputs[src.real_output][1].dest),
                crypto.scalarmult_base(kout)):
            raise ValueError("Invariant error")

        return self