Ejemplo n.º 1
0
    def test_range_proof3(self):
        proof = ring_ct.prove_range(123456789)
        rsig = proof[2]

        monero.recode_rangesig(rsig, encode=False)
        monero.recode_rangesig(rsig, encode=True)
        res = ring_ct.ver_range(proof[0], rsig)
        self.assertTrue(res)
Ejemplo n.º 2
0
 def test_range_proof_old(self):
     proof = ring_ct.prove_range(0,
                                 use_asnl=True,
                                 mem_opt=False,
                                 decode=True)
     res = ring_ct.ver_range(proof[0],
                             proof[2],
                             use_asnl=True,
                             decode=False)
     self.assertTrue(res)
Ejemplo n.º 3
0
    def test_range_proof2_back(self):
        proof = ring_ct.prove_range(123456789, backend_impl=True)
        res = ring_ct.ver_range(proof[0], proof[2])
        self.assertTrue(res)

        res = ring_ct.ver_range(
            crypto.point_add(proof[0], crypto.scalarmult_base(crypto.sc_init(4))),
            proof[2],
        )
        self.assertFalse(res)
Ejemplo n.º 4
0
    def test_range_proof(self):
        proof = ring_ct.prove_range(0)
        res = ring_ct.ver_range(proof[0], proof[2])
        self.assertTrue(res)
        self.assertTrue(
            crypto.point_eq(
                proof[0],
                crypto.point_add(crypto.scalarmult_base(proof[1]),
                                 crypto.scalarmult_h(0)),
            ))

        proof = ring_ct.prove_range(0, mem_opt=False)
        res = ring_ct.ver_range(proof[0], proof[2])
        self.assertTrue(res)
        self.assertTrue(
            crypto.point_eq(
                proof[0],
                crypto.point_add(crypto.scalarmult_base(proof[1]),
                                 crypto.scalarmult_h(0)),
            ))
Ejemplo n.º 5
0
    def test_range_proof2(self):
        amount = 17 + (1 << 60)
        proof = ring_ct.prove_range(amount)
        res = ring_ct.ver_range(proof[0], proof[2])
        self.assertTrue(res)
        self.assertTrue(
            crypto.point_eq(
                proof[0],
                crypto.point_add(crypto.scalarmult_base(proof[1]),
                                 crypto.scalarmult_h(amount)),
            ))

        proof = ring_ct.prove_range(amount, mem_opt=False, decode=True)
        res = ring_ct.ver_range(proof[0], proof[2], decode=False)
        self.assertTrue(res)

        res = ring_ct.ver_range(
            crypto.point_add(proof[0],
                             crypto.scalarmult_base(crypto.sc_init(4))),
            proof[2],
            decode=False,
        )
        self.assertFalse(res)
Ejemplo n.º 6
0
 def test_range_proof2_old(self):
     proof = ring_ct.prove_range(123456789,
                                 use_asnl=True,
                                 mem_opt=False,
                                 decode=True)
     res = ring_ct.ver_range(proof[0],
                             proof[2],
                             use_asnl=True,
                             decode=False)
     self.assertTrue(res)
     res = ring_ct.ver_range(
         crypto.point_add(proof[0],
                          crypto.scalarmult_base(crypto.sc_init(4))),
         proof[2],
         use_asnl=True,
         decode=False,
     )
     self.assertFalse(res)
Ejemplo n.º 7
0
 def test_range_proof_back(self):
     proof = ring_ct.prove_range(0, backend_impl=True)
     res = ring_ct.ver_range(proof[0], proof[2])
     self.assertTrue(res)
Ejemplo n.º 8
0
    async def gen_rct_header(self, destinations, outamounts):
        """
        Initializes RV RctSig structure, processes outputs, computes range proofs, ecdh info masking.
        Common to gen_rct and gen_rct_simple.

        :param destinations:
        :param outamounts:
        :return:
        """
        rv = xmrtypes.RctSig()
        rv.p = xmrtypes.RctSigPrunable()

        rv.message = self.tx_prefix_hash
        rv.outPk = [None] * len(destinations)

        if self.use_bulletproof:
            rv.p.bulletproofs = [None] * len(destinations)
        else:
            rv.p.rangeSigs = [None] * len(destinations)
        rv.ecdhInfo = [None] * len(destinations)

        # Output processing
        sumout = crypto.sc_0()
        out_sk = [None] * len(destinations)
        for idx in range(len(destinations)):
            rv.outPk[idx] = xmrtypes.CtKey(dest=crypto.encodepoint(destinations[idx]))
            C, mask, rsig = None, 0, None

            # Rangeproof
            if self.use_bulletproof:
                raise ValueError("Bulletproof not yet supported")

            else:
                C, mask, rsig = ring_ct.prove_range(outamounts[idx])
                rv.p.rangeSigs[idx] = rsig
                if __debug__:
                    assert ring_ct.ver_range(C, rsig)
                    assert crypto.point_eq(
                        C,
                        crypto.point_add(
                            crypto.scalarmult_base(mask),
                            crypto.scalarmult_h(outamounts[idx]),
                        ),
                    )

            # Mask sum
            rv.outPk[idx].mask = crypto.encodepoint(C)
            sumout = crypto.sc_add(sumout, mask)
            out_sk[idx] = xmrtypes.CtKey(mask=mask)

            # ECDH masking
            amount_key = crypto.encodeint(self.output_secrets[idx][0])
            rv.ecdhInfo[idx] = xmrtypes.EcdhTuple(
                mask=mask, amount=crypto.sc_init(outamounts[idx])
            )
            rv.ecdhInfo[idx] = ring_ct.ecdh_encode(
                rv.ecdhInfo[idx], derivation=amount_key
            )
            monero.recode_ecdh(rv.ecdhInfo[idx], encode=True)

        return rv, sumout, out_sk
Ejemplo n.º 9
0
    async def range_proof(self, idx, dest_pub_key, amount, amount_key):
        """
        Computes rangeproof and related information - out_sk, out_pk, ecdh_info.
        In order to optimize incremental transaction build, the mask computation is changed compared
        to the official Monero code. In the official code, the input pedersen commitments are computed
        after range proof in such a way summed masks for commitments (alpha) and rangeproofs (ai) are equal.

        In order to save roundtrips we compute commitments randomly and then for the last rangeproof
        a[63] = (\\sum_{i=0}^{num_inp}alpha_i - \\sum_{i=0}^{num_outs-1} amasks_i) - \\sum_{i=0}^{62}a_i

        The range proof is incrementally hashed to the final_message.

        :param idx:
        :param dest_pub_key:
        :param amount:
        :param amount_key:
        :return:
        """
        from monero_glue.xmr import ring_ct

        rsig = bytearray(32 * (64 + 64 + 64 + 1))
        rsig_mv = memoryview(rsig)

        out_pk = misc.StdObj(dest=dest_pub_key, mask=None)
        is_last = idx + 1 == self.num_dests()
        last_mask = (
            None
            if not is_last or not self.use_simple_rct
            else crypto.sc_sub(self.sumpouts_alphas, self.sumout)
        )

        # Pedersen commitment on the value, mask from the commitment, range signature.
        C, mask, rsig = None, 0, None

        # Rangeproof
        gc.collect()
        if self.use_bulletproof:
            raise ValueError("Bulletproof not yet supported")

        else:
            C, mask, rsig = ring_ct.prove_range(
                amount, last_mask, backend_impl=True, byte_enc=True, rsig=rsig_mv
            )
            rsig = memoryview(rsig)

            if __debug__:
                rsig_bytes = monero.inflate_rsig(rsig)
                self.assrt(ring_ct.ver_range(C, rsig_bytes))

            self.assrt(
                crypto.point_eq(
                    C,
                    crypto.point_add(
                        crypto.scalarmult_base(mask), crypto.scalarmult_h(amount)
                    ),
                ),
                "rproof",
            )

            # Incremental hashing
            await self.full_message_hasher.rsig_val(
                rsig, self.use_bulletproof, raw=True
            )
        gc.collect()
        self._log_trace("rproof")

        # Mask sum
        out_pk.mask = crypto.encodepoint(C)
        self.sumout = crypto.sc_add(self.sumout, mask)
        self.output_sk.append(misc.StdObj(mask=mask))

        # ECDH masking
        from monero_glue.xmr.sub.recode import recode_ecdh
        from monero_serialize.xmrtypes import EcdhTuple

        ecdh_info = EcdhTuple(mask=mask, amount=crypto.sc_init(amount))
        ecdh_info = ring_ct.ecdh_encode(
            ecdh_info, derivation=crypto.encodeint(amount_key)
        )
        recode_ecdh(ecdh_info, encode=True)
        gc.collect()

        return rsig, out_pk, ecdh_info