From a78be65214bccd932f9d8374069667d389b949f4 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Thu, 29 Sep 2022 10:58:59 +0000 Subject: [PATCH] support Monero integrated addresses --- mmgen/data/release_date | 2 +- mmgen/data/version | 2 +- mmgen/proto/xmr.py | 11 +++++++---- mmgen/xmrwallet.py | 5 +++++ test/unit_tests_d/ut_addrparse.py | 15 ++++++++++++++- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/mmgen/data/release_date b/mmgen/data/release_date index 62af01c2..121322d7 100644 --- a/mmgen/data/release_date +++ b/mmgen/data/release_date @@ -1 +1 @@ -August 2022 +September 2022 diff --git a/mmgen/data/version b/mmgen/data/version index 67aee239..b1b9f0ad 100644 --- a/mmgen/data/version +++ b/mmgen/data/version @@ -1 +1 @@ -13.2.0 +13.3.dev0 diff --git a/mmgen/proto/xmr.py b/mmgen/proto/xmr.py index 447ca935..d6f90481 100755 --- a/mmgen/proto/xmr.py +++ b/mmgen/proto/xmr.py @@ -16,7 +16,7 @@ from collections import namedtuple from ..protocol import CoinProtocol,_nw -parsed_addr = namedtuple('parsed_addr',['ver_bytes','data']) +parsed_addr = namedtuple('parsed_addr',['ver_bytes','data','payment_id']) # https://github.com/monero-project/monero/blob/master/src/cryptonote_config.h class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Base): @@ -24,8 +24,7 @@ class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Base): network_names = _nw('mainnet','stagenet',None) base_coin = 'XMR' base_proto = 'Monero' - addr_ver_bytes = { '12': 'monero', '2a': 'monero_sub' } - addr_len = 64 + addr_ver_bytes = { '12': 'monero', '2a': 'monero_sub', '13': 'monero_integrated' } wif_ver_num = {} pubkey_types = ('monero',) mmtypes = ('M',) @@ -37,6 +36,9 @@ class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Base): ignore_daemon_version = False coin_amt = 'XMRAmt' + def get_addr_len(self,addr_fmt): + return (64,72)[addr_fmt == 'monero_integrated'] + def preprocess_key(self,sec,pubkey_type): # reduce key from ..contrib.ed25519 import l return int.to_bytes( @@ -68,10 +70,11 @@ class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Base): return parsed_addr( ver_bytes = ver_bytes, data = addr_bytes[:addr_len], + payment_id = addr_bytes[addr_len:] if fmt == 'monero_integrated' else None, ) def pubhash2addr(self,*args,**kwargs): raise NotImplementedError('Monero addresses do not support pubhash2addr()') class testnet(mainnet): # use stagenet for testnet - addr_ver_bytes = { '18': 'monero', '24': 'monero_sub' } # testnet is ('35','3f') + addr_ver_bytes = { '18': 'monero', '24': 'monero_sub', '19': 'monero_integrated' } # testnet is {'35','3f','36'} diff --git a/mmgen/xmrwallet.py b/mmgen/xmrwallet.py index b6fdf70d..81adc0ed 100755 --- a/mmgen/xmrwallet.py +++ b/mmgen/xmrwallet.py @@ -137,6 +137,10 @@ class MoneroMMGenTX: Dest: {} """ + pmid = d.dest_address.parsed.payment_id + if pmid: + fs += ' Payment ID: {pmid}' + return fmt(fs,strip_char='\t',indent=indent).format( d.seed_id.hl(), d.network.upper(), d.txid.hl(), @@ -147,6 +151,7 @@ class MoneroMMGenTX: d.amount.hl(), d.fee.hl(), d.dest_address.hl(), + pmid = pink(pmid.hex()) if pmid else None ) def write(self,delete_metadata=False): diff --git a/test/unit_tests_d/ut_addrparse.py b/test/unit_tests_d/ut_addrparse.py index add4c4bf..2e2191bb 100755 --- a/test/unit_tests_d/ut_addrparse.py +++ b/test/unit_tests_d/ut_addrparse.py @@ -19,8 +19,13 @@ vectors = { 'xmr_mainnet': [ { # ut_xmrseed.vectors[0]: 'std': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', +# https://github.com/monero-project/monero/tests/functional_tests/integrated_address.py +'int': '4CMe2PUhs4J4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfSbLRB61BQVATzerHGj', +'id': '0123456789abcdef' },{ 'std': '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', +'int': '4GYjoMG9Y2BBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCVSs1ZojwrDCGS5rUuo', +'id': '1122334455667788' } ], 'zec_mainnet': [ @@ -43,7 +48,7 @@ def test_network(proto,addrs): addr.parsed.ver_bytes, proto.addr_fmt_to_ver_bytes.get(addr.addr_fmt) ) check_equal( - addr.parsed.data, + addr.parsed.data + ((addr.parsed.payment_id or b'') if proto.coin == 'XMR' else b''), addr.bytes ) def fmt_addr_data(addr): @@ -64,6 +69,14 @@ def test_network(proto,addrs): a1 = CoinAddr(proto,addr['std']) print_info(a1) check_bytes(a1) + assert not hasattr(a1.parsed,'payment_id') or a1.parsed.payment_id == None + + if 'int' in addr: + a2 = CoinAddr(proto,addr['int']) + print_info(a2) + check_bytes(a2) + check_equal( a1.parsed.data, a2.parsed.data ) + check_equal( a2.parsed.payment_id, bytes.fromhex(addr['id']) ) msg('OK') vmsg('')