Last active
September 13, 2021 02:15
-
-
Save ph4r05/b95c085b101cd9c9ba5dad104dfab007 to your computer and use it in GitHub Desktop.
Fixes payment ID problem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# pip install monero_agent>=1.7.6 | |
import binascii | |
import json | |
import requests | |
from monero_glue.xmr import crypto | |
from monero_serialize.xmrserialize import load_uvarint_b, uvarint_size | |
# Set your values here: | |
daemon_addr = 'opennode.xmr-tw.org:18089' | |
txid = '2331873ba8d7d2b935e2d89b36ebe2c031a2f785fc799a4fb4641385c098c66d' | |
viewkey = 'f27ab2ae6c9849601b15d55da305f02b6a4e373432f280a78263eb137ca36603' # viewkey command in monero-wallet-cli, the private (secret) part | |
def parse_payment_id(extra): | |
offset = 0 | |
extra = bytearray(extra) | |
pub_key = None | |
payment_id = None | |
nonce = None | |
while offset < len(extra): | |
tag = extra[offset] | |
offset += 1 | |
if tag == 0x1: # pubkey | |
pub_key = extra[offset : offset + 32] | |
offset += 32 | |
elif tag == 0x2: # nonce | |
ln = load_uvarint_b(extra[offset:]) | |
offset += uvarint_size(ln) | |
nonce = extra[offset : offset + ln] | |
offset += ln | |
elif tag == 0x4: # additionals | |
ln = load_uvarint_b(extra[offset:]) | |
offset += uvarint_size(ln) + 32 * ln | |
else: | |
raise ValueError('Not Trezor transaction') | |
if nonce and len(nonce) == 9 and nonce[0] == 1: | |
payment_id = nonce[1:] | |
if not payment_id or not pub_key: | |
raise ValueError('Payment ID or pubkey not found in TX') | |
return pub_key, payment_id | |
def encrypt_payment_id(payment_id, public_key, secret_key, tag): | |
derivation_p = crypto.generate_key_derivation(public_key, secret_key) | |
derivation = bytearray(33) | |
derivation = crypto.encodepoint_into(derivation, derivation_p) | |
derivation[32] = tag # ENCRYPTED_PAYMENT_ID_TAIL | |
hash = crypto.cn_fast_hash(derivation) | |
pm_copy = bytearray(payment_id) | |
for i in range(8): | |
pm_copy[i] ^= hash[i] | |
return pm_copy | |
def fix_payment_id(daemon_addr, txid, viewkey): | |
res = requests.post('http://%s/gettransactions' % daemon_addr, json={"txs_hashes":[txid], "decode_as_json": True}) | |
txjs = json.loads([x['as_json'] for x in res.json()['txs'] if x['tx_hash'] == txid][0]) | |
extra = bytearray(txjs['extra']) | |
pub_bin, payment_id = parse_payment_id(extra) | |
pub = crypto.decodepoint(pub_bin) | |
viewkey_bin = binascii.unhexlify(viewkey) | |
viewkey_sec = crypto.decodeint(viewkey_bin) | |
return encrypt_payment_id(payment_id, pub, viewkey_sec, 0x8b) | |
if __name__ == '__main__': | |
fixed = fix_payment_id(daemon_addr, txid, viewkey) | |
print('Fixed: %s for txid %s' % (binascii.hexlify(fixed), txid)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment