params.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2025 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen-wallet
  9. # https://gitlab.com/mmgen/mmgen-wallet
  10. """
  11. proto.xmr.params: Monero protocol
  12. """
  13. from collections import namedtuple
  14. from ...protocol import CoinProtocol, _nw
  15. from ...obj import HexStr
  16. parsed_addr = namedtuple('parsed_addr', ['ver_bytes', 'data', 'payment_id'])
  17. class MoneroViewKey(HexStr):
  18. color, width, hexcase = 'cyan', 64, 'lower' # FIXME - no checking performed
  19. # https://github.com/monero-project/monero/blob/master/src/cryptonote_config.h
  20. class mainnet(CoinProtocol.RPC, CoinProtocol.DummyWIF, CoinProtocol.Base):
  21. mod_clsname = 'Monero'
  22. network_names = _nw('mainnet', 'stagenet', None)
  23. base_proto = 'Monero'
  24. base_proto_coin = 'XMR'
  25. base_coin = 'XMR'
  26. addr_ver_info = {'12': 'monero', '2a': 'monero_sub', '13': 'monero_integrated'}
  27. pubkey_types = ('monero',)
  28. mmtypes = ('M',)
  29. dfl_mmtype = 'M'
  30. pubkey_type = 'monero' # required by DummyWIF
  31. avg_bdi = 120
  32. privkey_len = 32
  33. mmcaps = ('rpc', 'tw')
  34. coin_amt = 'XMRAmt'
  35. sign_mode = 'standalone'
  36. has_usr_fee = False
  37. coin_cfg_opts = (
  38. 'ignore_daemon_version',
  39. 'rpc_port',
  40. )
  41. def get_addr_len(self, addr_fmt):
  42. return (64, 72)[addr_fmt == 'monero_integrated']
  43. def preprocess_key(self, sec, pubkey_type): # reduce key
  44. from ...contrib.ed25519 import l
  45. return int.to_bytes(
  46. int.from_bytes(sec[::-1], 'big') % l,
  47. self.privkey_len,
  48. 'big')[::-1]
  49. def decode_addr(self, addr):
  50. from ...baseconv import baseconv
  51. def b58dec(addr_str):
  52. bc = baseconv('b58')
  53. l = len(addr_str)
  54. a = b''.join([bc.tobytes(addr_str[i*11:i*11+11], pad=8) for i in range(l//11)])
  55. b = bc.tobytes(addr_str[-(l%11):], pad=5)
  56. return a + b
  57. ret = b58dec(addr)
  58. chk = self.keccak_256(ret[:-4]).digest()[:4]
  59. assert ret[-4:] == chk, f'{ret[-4:].hex()}: incorrect checksum. Correct value: {chk.hex()}'
  60. return self.decode_addr_bytes(ret[:-4])
  61. def parse_addr(self, ver_bytes, addr_bytes, fmt):
  62. addr_len = self.get_addr_len('monero')
  63. return parsed_addr(
  64. ver_bytes = ver_bytes,
  65. data = addr_bytes[:addr_len],
  66. payment_id = addr_bytes[addr_len:] if fmt == 'monero_integrated' else None,
  67. )
  68. def pubhash2addr(self, *args, **kwargs):
  69. raise NotImplementedError('Monero addresses do not support pubhash2addr()')
  70. def viewkey(self, viewkey_str):
  71. return MoneroViewKey.__new__(MoneroViewKey, viewkey_str)
  72. class testnet(mainnet): # use stagenet for testnet
  73. # testnet is {'35', '3f', '36'}
  74. addr_ver_info = {'18': 'monero', '24': 'monero_sub', '19': 'monero_integrated'}