j-berman 2 years ago committed by Michał Sałaban
parent 00c0955989
commit ece5b9d4cd

@ -7,6 +7,15 @@ scalar_add = nacl.bindings.crypto_core_ed25519_scalar_add
scalarmult_B = nacl.bindings.crypto_scalarmult_ed25519_base_noclamp
scalarmult = nacl.bindings.crypto_scalarmult_ed25519_noclamp
# https://github.com/monero-project/monero/blob/9f814edbd78c70c70b814ca934c1ddef58768262/src/ringct/rctTypes.h#L615
H = binascii.unhexlify(
"8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94"
)
def scalarmult_H(v):
return scalarmult(v, H)
def scalar_reduce(v):
return nacl.bindings.crypto_core_ed25519_scalar_reduce(v + (64 - len(v)) * b"\0")

@ -140,7 +140,7 @@ class Transaction(object):
already generated.
"""
def _scan_pubkeys(svk, psk, stealth_address, amount, encamount):
def _scan_pubkeys(svk, psk, stealth_address, amount, encamount, commitment):
for keyidx, tx_key in enumerate(self.pubkeys):
# precompute
svk_2 = ed25519.scalar_add(svk, svk)
@ -174,14 +174,22 @@ class Transaction(object):
dec_amount = bytearray(
a ^ b for a, b in zip(*map(bytearray, (encamount, xormask)))
)
int_amount = struct.unpack("<Q", dec_amount)[0]
amount = from_atomic(int_amount)
return Payment(
amount=amount,
timestamp=self.timestamp,
transaction=self,
local_address=addr,
)
# verify that the commitment == yG + bH
# https://web.getmonero.org/library/Zero-to-Monero-2-0-0.pdf#section.5.3
y = ed25519.scalar_reduce(keccak_256(b"commitment_mask" + Hs).digest())
yG = ed25519.scalarmult_B(y)
b = ed25519.scalar_reduce(bytes(dec_amount))
bH = ed25519.scalarmult_H(b)
amount = 0
if commitment == ed25519.edwards_add(yG, bH):
int_amount = struct.unpack("<Q", dec_amount)[0]
amount = from_atomic(int_amount)
return Payment(
amount=amount,
timestamp=self.timestamp,
transaction=self,
local_address=addr,
)
if not self.json:
raise exceptions.TransactionWithoutJSON(
@ -203,10 +211,14 @@ class Transaction(object):
for idx, vout in enumerate(self.json["vout"]):
stealth_address = binascii.unhexlify(vout["target"]["key"])
encamount = None
commitment = None
if self.version == 2 and not self.is_coinbase:
encamount = binascii.unhexlify(
self.json["rct_signatures"]["ecdhInfo"][idx]["amount"]
)
commitment = binascii.unhexlify(
self.json["rct_signatures"]["outPk"][idx]
)
payment = None
amount = (
from_atomic(vout["amount"])
@ -217,7 +229,7 @@ class Transaction(object):
for addridx, addr in enumerate(addresses):
psk = binascii.unhexlify(addr.spend_key())
payment = _scan_pubkeys(
svk, psk, stealth_address, amount, encamount
svk, psk, stealth_address, amount, encamount, commitment
)
if payment:
break

Loading…
Cancel
Save