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)
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)
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)
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)), ))
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)
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)
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)
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
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