1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-16 03:18:09 +00:00

xmr: step_09_sign - manual MgSig serialization

This commit is contained in:
Dusan Klinec 2018-11-01 18:20:31 +01:00
parent 90fd0bb67a
commit a462ea35ce
No known key found for this signature in database
GPG Key ID: 6337E118CCBCE103

View File

@ -10,7 +10,8 @@ from .state import State
from apps.monero.layout import confirms from apps.monero.layout import confirms
from apps.monero.signing import RctType from apps.monero.signing import RctType
from apps.monero.xmr import crypto, serialize from apps.monero.xmr import crypto
from apps.monero.xmr.serialize import int_serialize
if False: if False:
from trezor.messages.MoneroTransactionSourceEntry import ( from trezor.messages.MoneroTransactionSourceEntry import (
@ -66,7 +67,7 @@ async def sign_input(
raise ValueError("HMAC is not correct") raise ValueError("HMAC is not correct")
gc.collect() gc.collect()
state.mem_trace(1) state.mem_trace(1, True)
if state.rct_type == RctType.Simple: if state.rct_type == RctType.Simple:
# both pseudo_out and its mask were offloaded so we need to # both pseudo_out and its mask were offloaded so we need to
@ -78,8 +79,7 @@ async def sign_input(
if not crypto.ct_equals(pseudo_out_hmac_comp, pseudo_out_hmac): if not crypto.ct_equals(pseudo_out_hmac_comp, pseudo_out_hmac):
raise ValueError("HMAC is not correct") raise ValueError("HMAC is not correct")
gc.collect() state.mem_trace(2, True)
state.mem_trace(2)
from apps.monero.xmr.crypto import chacha_poly from apps.monero.xmr.crypto import chacha_poly
@ -102,8 +102,7 @@ async def sign_input(
) )
) )
gc.collect() state.mem_trace(3, True)
state.mem_trace(3)
# Basic setup, sanity check # Basic setup, sanity check
index = src_entr.real_output index = src_entr.real_output
@ -126,13 +125,15 @@ async def sign_input(
"Real source entry's mask does not equal spend key's", "Real source entry's mask does not equal spend key's",
) )
gc.collect() state.mem_trace(4, True)
state.mem_trace(4) mg_buff = bytearray(_mg_size(len(src_entr.outputs)))
from apps.monero.xmr import mlsag from apps.monero.xmr import mlsag
if state.rct_type == RctType.Simple: if state.rct_type == RctType.Simple:
ring_pubkeys = [x.key for x in src_entr.outputs] ring_pubkeys = [x.key for x in src_entr.outputs]
src_entr = None
mg = mlsag.generate_mlsag_simple( mg = mlsag.generate_mlsag_simple(
state.full_message, state.full_message,
ring_pubkeys, ring_pubkeys,
@ -143,10 +144,14 @@ async def sign_input(
index, index,
) )
del (ring_pubkeys, input_secret_key, pseudo_out_alpha, pseudo_out_c)
else: else:
# Full RingCt, only one input # Full RingCt, only one input
txn_fee_key = crypto.scalarmult_h(state.fee) txn_fee_key = crypto.scalarmult_h(state.fee)
ring_pubkeys = [[x.key] for x in src_entr.outputs] ring_pubkeys = [[x.key] for x in src_entr.outputs]
src_entr = None
mg = mlsag.generate_mlsag_full( mg = mlsag.generate_mlsag_full(
state.full_message, state.full_message,
ring_pubkeys, ring_pubkeys,
@ -158,35 +163,70 @@ async def sign_input(
txn_fee_key, txn_fee_key,
) )
gc.collect() del (ring_pubkeys, input_secret_key, txn_fee_key)
state.mem_trace(5)
del (mlsag, src_entr)
state.mem_trace(5, True)
# Encode # Encode
mgs = _recode_msg([mg]) mg_buffer = _mg_serialize(mg, mg_buff)
state.mem_trace(6, True)
gc.collect()
state.mem_trace(6)
from trezor.messages.MoneroTransactionSignInputAck import ( from trezor.messages.MoneroTransactionSignInputAck import (
MoneroTransactionSignInputAck, MoneroTransactionSignInputAck,
) )
return MoneroTransactionSignInputAck( return MoneroTransactionSignInputAck(signature=mg_buffer)
signature=serialize.dump_msg_gc(mgs[0], preallocate=488)
)
def _recode_msg(mgs): def _mg_size(num_outs):
""" """
Recodes MGs signatures from raw forms to bytearrays so it works with serialization Computes size of the MgSig
:param num_outs:
:return:
""" """
for idx in range(len(mgs)): size = 32 # cc
mgs[idx].cc = crypto.encodeint(mgs[idx].cc) mg_cols = num_outs
if hasattr(mgs[idx], "II") and mgs[idx].II: mg_rows = 2
for i in range(len(mgs[idx].II)): cols_b_size = int_serialize.uvarint_size(mg_cols)
mgs[idx].II[i] = crypto.encodepoint(mgs[idx].II[i]) rows_b_size = 1
size += cols_b_size + mg_cols * (rows_b_size + mg_rows * 32)
return size
for i in range(len(mgs[idx].ss)):
for j in range(len(mgs[idx].ss[i])): def _mg_serialize(mg, buff):
mgs[idx].ss[i][j] = crypto.encodeint(mgs[idx].ss[i][j]) """
return mgs Serializes MgSig structure: (("ss", KeyM), ("cc", ECKey))
:param mg:
:return:
"""
size = len(buff)
mg_cols = len(mg.ss)
mg_rows = len(mg.ss[0])
cols_b_size = int_serialize.uvarint_size(mg_cols)
rows_b_size = int_serialize.uvarint_size(mg_rows)
offset = 0
int_serialize.dump_uvarint_b_into(mg_cols, buff, offset)
offset += cols_b_size
for i in range(mg_cols):
utils.ensure(len(mg.ss[i]) == mg_rows, "Irregular matrix shape")
int_serialize.dump_uvarint_b_into(mg_rows, buff, offset)
offset += rows_b_size
for j in range(mg_rows):
crypto.encodeint_into(buff, mg.ss[i][j], offset)
offset += 32
mg.ss[i] = None
gc.collect()
mg.ss = None
crypto.encodeint_into(buff, mg.cc, offset)
offset += 32
utils.ensure(offset == size, "Invalid mg size computation")
return buff