Skip to content

Commit

Permalink
xmr: borromean range sig generated by partitions
Browse files Browse the repository at this point in the history
- overcomes heap fragmentation problem
  • Loading branch information
ph4r05 committed Sep 17, 2018
1 parent 65a5116 commit 18604e0
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 35 deletions.
15 changes: 6 additions & 9 deletions src/apps/monero/protocol/tsx_sign_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,10 @@ def _return_rsig_data(self, rsig):
return None
from trezor.messages.MoneroTransactionRsigData import MoneroTransactionRsigData

return MoneroTransactionRsigData(rsig=rsig)
if isinstance(rsig, list):
return MoneroTransactionRsigData(rsig_parts=rsig)
else:
return MoneroTransactionRsigData(rsig=rsig)

def _range_proof(self, idx, amount, rsig_data=None):
"""
Expand Down Expand Up @@ -929,14 +932,8 @@ def _range_proof(self, idx, amount, rsig_data=None):
)

elif not self.rsig_offload and not self.use_bulletproof:
rsig_buff = bytearray(32 * (64 + 64 + 64 + 1))
rsig_mv = memoryview(rsig_buff)

C, mask, rsig = ring_ct.prove_range(
amount, mask, backend_impl=True, byte_enc=True, rsig=rsig_mv
)
rsig = memoryview(rsig)
del (rsig_buff, rsig_mv, ring_ct)
C, mask, rsig = ring_ct.prove_range_chunked(amount, mask)
del (ring_ct)

# Incremental hashing
self.full_message_hasher.rsig_val(rsig, False, raw=True)
Expand Down
4 changes: 4 additions & 0 deletions src/apps/monero/xmr/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ def point_double(P):
return tcry.ge25519_double(P)


def point_double_into(r, P):
return tcry.ge25519_double(r, P)


def point_mul8(P):
return tcry.ge25519_mul8(P)

Expand Down
116 changes: 91 additions & 25 deletions src/apps/monero/xmr/ring_ct.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,36 +61,102 @@ def verify_bp(bp_proof, amounts=None, masks=None):
return res


def prove_range(
amount, last_mask=None, decode=False, backend_impl=True, byte_enc=True, rsig=None
):
"""
Range proof generator.
In order to minimize the memory consumption and CPU usage during transaction generation the returned values
are returned encoded.
"""
if not backend_impl or not byte_enc or decode:
raise ValueError("Unsupported params")
def prove_range_chunked(amount, last_mask=None):
a = crypto.sc_init(0)
si = crypto.sc_init(0)
c = crypto.sc_init(0)
ee = crypto.sc_init(0)
tmp_ai = crypto.sc_init(0)
tmp_alpha = crypto.sc_init(0)

C_acc = crypto.identity()
C_h = crypto.gen_H()
C_tmp = crypto.identity()
L = crypto.identity()
Zero = crypto.identity()
kck = crypto.get_keccak()

ai = bytearray(32 * 64)
alphai = bytearray(32 * 64)
buff = bytearray(32)

Cis = bytearray(32 * 64)
s0s = bytearray(32 * 64)
s1s = bytearray(32 * 64)
ee_bin = bytearray(32)

for ii in range(64):
crypto.random_scalar_into(tmp_ai)
if last_mask is not None and ii == 63:
crypto.sc_sub_into(tmp_ai, last_mask, a)

crypto.sc_add_into(a, a, tmp_ai)
crypto.random_scalar_into(tmp_alpha)

crypto.scalarmult_base_into(L, tmp_alpha)
crypto.scalarmult_base_into(C_tmp, tmp_ai)

# C_tmp += &Zero if BB(ii) == 0 else &C_h
crypto.point_add_into(C_tmp, C_tmp, Zero if ((amount >> ii) & 1) == 0 else C_h)
crypto.point_add_into(C_acc, C_acc, C_tmp)

# Set Ci[ii] to sigs
crypto.encodepoint_into(Cis, C_tmp, ii << 5)
crypto.encodeint_into(ai, tmp_ai, ii << 5)
crypto.encodeint_into(alphai, tmp_alpha, ii << 5)

if ((amount >> ii) & 1) == 0:
crypto.random_scalar_into(si)
crypto.encodepoint_into(buff, L)
crypto.hash_to_scalar_into(c, buff)

crypto.point_sub_into(C_tmp, C_tmp, C_h)
crypto.add_keys2_into(L, si, c, C_tmp)

crypto.encodeint_into(s1s, si, ii << 5)

crypto.encodepoint_into(buff, L)
kck.update(buff)

crypto.point_double_into(C_h, C_h)

# Compute ee
tmp_ee = kck.digest()
crypto.decodeint_into(ee, tmp_ee)
del (tmp_ee, kck)

C_h = crypto.gen_H()
gc.collect()

# Second pass, s0, s1
for ii in range(64):
crypto.decodeint_into(tmp_alpha, alphai, ii << 5)
crypto.decodeint_into(tmp_ai, ai, ii << 5)

C, a, R = None, None, None
try:
if rsig is None:
rsig = bytearray(32 * (64 + 64 + 64 + 1))
if ((amount >> ii) & 1) == 0:
crypto.sc_mulsub_into(si, tmp_ai, ee, tmp_alpha)
crypto.encodeint_into(s0s, si, ii << 5)

buf_ai = bytearray(4 * 9 * 64)
buf_alpha = bytearray(4 * 9 * 64)
C, a, R = crypto.prove_range(
rsig, amount, last_mask, buf_ai, buf_alpha
) # backend returns encoded
else:
crypto.random_scalar_into(si)
crypto.encodeint_into(s0s, si, ii << 5)

crypto.decodepoint_into(C_tmp, Cis, ii << 5)
crypto.add_keys2_into(L, si, ee, C_tmp)
crypto.encodepoint_into(buff, L)
crypto.hash_to_scalar_into(c, buff)

crypto.sc_mulsub_into(si, tmp_ai, c, tmp_alpha)
crypto.encodeint_into(s1s, si, ii << 5)

finally:
import gc
crypto.point_double_into(C_h, C_h)

buf_ai = None
buf_alpha = None
gc.collect()
crypto.encodeint_into(ee_bin, ee)

del (ai, alphai, buff, tmp_ai, tmp_alpha, si, c, ee, C_tmp, C_h, L, Zero)
gc.collect()

return C, a, R
return C_acc, a, [s0s, s1s, ee_bin, Cis]


# Ring-ct MG sigs
Expand Down
6 changes: 5 additions & 1 deletion src/apps/monero/xmr/sub/mlsag_hasher.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ def rsig_val(self, p, bulletproof, raw=False):
raise ValueError("State error")

if raw:
self.rsig_hasher.update(p)
if isinstance(p, list):
for x in p:
self.rsig_hasher.update(x)
else:
self.rsig_hasher.update(p)
return

if bulletproof:
Expand Down

0 comments on commit 18604e0

Please sign in to comment.