Allow multiple base58 prefix bytes.

2024-05-20_merge
tecnovert 9 months ago
parent 2a28f336e2
commit 1cbc2f44b0
No known key found for this signature in database
GPG Key ID: 8ED6D8750C4E3F93
  1. 3
      basicswap/chainparams.py
  2. 16
      basicswap/interface/xmr.py
  3. 2
      basicswap/util/__init__.py
  4. 23
      basicswap/util/integer.py
  5. 6
      basicswap/util_xmr.py
  6. 31
      tests/basicswap/test_other.py

@ -200,18 +200,21 @@ chainparams = {
'walletrpcport': 18082, 'walletrpcport': 18082,
'min_amount': 100000, 'min_amount': 100000,
'max_amount': 10000 * XMR_COIN, 'max_amount': 10000 * XMR_COIN,
'address_prefix': 18,
}, },
'testnet': { 'testnet': {
'rpcport': 28081, 'rpcport': 28081,
'walletrpcport': 28082, 'walletrpcport': 28082,
'min_amount': 100000, 'min_amount': 100000,
'max_amount': 10000 * XMR_COIN, 'max_amount': 10000 * XMR_COIN,
'address_prefix': 18,
}, },
'regtest': { 'regtest': {
'rpcport': 18081, 'rpcport': 18081,
'walletrpcport': 18082, 'walletrpcport': 18082,
'min_amount': 100000, 'min_amount': 100000,
'max_amount': 10000 * XMR_COIN, 'max_amount': 10000 * XMR_COIN,
'address_prefix': 18,
} }
}, },
Coins.PIVX: { Coins.PIVX: {

@ -81,6 +81,8 @@ class XMRInterface(CoinInterface):
def __init__(self, coin_settings, network, swap_client=None): def __init__(self, coin_settings, network, swap_client=None):
super().__init__(network) super().__init__(network)
self._addr_prefix = self.chainparams_network()['address_prefix']
self.blocks_confirmed = coin_settings['blocks_confirmed'] self.blocks_confirmed = coin_settings['blocks_confirmed']
self._restore_height = coin_settings.get('restore_height', 0) self._restore_height = coin_settings.get('restore_height', 0)
self.setFeePriority(coin_settings.get('fee_priority', 2)) self.setFeePriority(coin_settings.get('fee_priority', 2))
@ -165,7 +167,7 @@ class XMRInterface(CoinInterface):
Kbv = self.getPubkey(key_view) Kbv = self.getPubkey(key_view)
Kbs = self.getPubkey(key_spend) Kbs = self.getPubkey(key_spend)
address_b58 = xmr_util.encode_address(Kbv, Kbs) address_b58 = xmr_util.encode_address(Kbv, Kbs, self._addr_prefix)
params = { params = {
'filename': self._wallet_filename, 'filename': self._wallet_filename,
@ -289,7 +291,7 @@ class XMRInterface(CoinInterface):
def getAddressFromKeys(self, key_view: bytes, key_spend: bytes) -> str: def getAddressFromKeys(self, key_view: bytes, key_spend: bytes) -> str:
pk_view = self.getPubkey(key_view) pk_view = self.getPubkey(key_view)
pk_spend = self.getPubkey(key_spend) pk_spend = self.getPubkey(key_spend)
return xmr_util.encode_address(pk_view, pk_spend) return xmr_util.encode_address(pk_view, pk_spend, self._addr_prefix)
def verifyKey(self, k: int) -> bool: def verifyKey(self, k: int) -> bool:
i = b2i(k) i = b2i(k)
@ -317,7 +319,7 @@ class XMRInterface(CoinInterface):
return ed25519_add(Ka, Kb) return ed25519_add(Ka, Kb)
def encodeSharedAddress(self, Kbv: bytes, Kbs: bytes) -> str: def encodeSharedAddress(self, Kbv: bytes, Kbs: bytes) -> str:
return xmr_util.encode_address(Kbv, Kbs) return xmr_util.encode_address(Kbv, Kbs, self._addr_prefix)
def publishBLockTx(self, kbv: bytes, Kbs: bytes, output_amount: int, feerate: int, unlock_time: int = 0) -> bytes: def publishBLockTx(self, kbv: bytes, Kbs: bytes, output_amount: int, feerate: int, unlock_time: int = 0) -> bytes:
with self._mx_wallet: with self._mx_wallet:
@ -325,7 +327,7 @@ class XMRInterface(CoinInterface):
self.rpc_wallet('refresh') self.rpc_wallet('refresh')
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
shared_addr = xmr_util.encode_address(Kbv, Kbs) shared_addr = xmr_util.encode_address(Kbv, Kbs, self._addr_prefix)
params = {'destinations': [{'amount': output_amount, 'address': shared_addr}], 'unlock_time': unlock_time} params = {'destinations': [{'amount': output_amount, 'address': shared_addr}], 'unlock_time': unlock_time}
if self._fee_priority > 0: if self._fee_priority > 0:
@ -339,7 +341,7 @@ class XMRInterface(CoinInterface):
def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height, bid_sender): def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height, bid_sender):
with self._mx_wallet: with self._mx_wallet:
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
address_b58 = xmr_util.encode_address(Kbv, Kbs) address_b58 = xmr_util.encode_address(Kbv, Kbs, self._addr_prefix)
kbv_le = kbv[::-1] kbv_le = kbv[::-1]
params = { params = {
@ -417,7 +419,7 @@ class XMRInterface(CoinInterface):
with self._mx_wallet: with self._mx_wallet:
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
Kbs = self.getPubkey(kbs) Kbs = self.getPubkey(kbs)
address_b58 = xmr_util.encode_address(Kbv, Kbs) address_b58 = xmr_util.encode_address(Kbv, Kbs, self._addr_prefix)
wallet_filename = address_b58 + '_spend' wallet_filename = address_b58 + '_spend'
@ -504,7 +506,7 @@ class XMRInterface(CoinInterface):
with self._mx_wallet: with self._mx_wallet:
try: try:
Kbv = self.getPubkey(kbv) Kbv = self.getPubkey(kbv)
address_b58 = xmr_util.encode_address(Kbv, Kbs) address_b58 = xmr_util.encode_address(Kbv, Kbs, self._addr_prefix)
wallet_file = address_b58 + '_spend' wallet_file = address_b58 + '_spend'
try: try:
self.openWallet(wallet_file) self.openWallet(wallet_file)

@ -67,6 +67,7 @@ def dumpje(jin):
def SerialiseNum(n: int) -> bytes: def SerialiseNum(n: int) -> bytes:
# For script
if n == 0: if n == 0:
return bytes((0x00,)) return bytes((0x00,))
if n > 0 and n <= 16: if n > 0 and n <= 16:
@ -85,6 +86,7 @@ def SerialiseNum(n: int) -> bytes:
def DeserialiseNum(b: bytes, o: int = 0) -> int: def DeserialiseNum(b: bytes, o: int = 0) -> int:
# For script
if b[o] == 0: if b[o] == 0:
return 0 return 0
if b[o] > 0x50 and b[o] <= 0x50 + 16: if b[o] > 0x50 and b[o] <= 0x50 + 16:

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
def decode_varint(b: bytes) -> int:
i = 0
shift = 0
for c in b:
i += (c & 0x7F) << shift
shift += 7
return i
def encode_varint(i: int) -> bytes:
b = bytearray()
while i > 0x7F:
b += bytes(((i & 0x7F) | 0x80,))
i = (i >> 7)
b += bytes((i,))
return b

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import basicswap.contrib.Keccak as Keccak import basicswap.contrib.Keccak as Keccak
from basicswap.util.integer import encode_varint
from .contrib.MoneroPy.base58 import encode as xmr_b58encode from .contrib.MoneroPy.base58 import encode as xmr_b58encode
@ -9,8 +10,9 @@ def cn_fast_hash(s):
return k.Keccak((len(s) * 8, s.hex()), 1088, 512, 32 * 8, False).lower() # r = bitrate = 1088, c = capacity, n = output length in bits return k.Keccak((len(s) * 8, s.hex()), 1088, 512, 32 * 8, False).lower() # r = bitrate = 1088, c = capacity, n = output length in bits
def encode_address(view_point, spend_point, version=18): def encode_address(view_point: bytes, spend_point: bytes, version=18) -> str:
buf = bytes((version,)) + spend_point + view_point prefix_bytes = version if isinstance(version, bytes) else encode_varint(version)
buf = prefix_bytes + spend_point + view_point
h = cn_fast_hash(buf) h = cn_fast_hash(buf)
buf = buf + bytes.fromhex(h[0: 8]) buf = buf + bytes.fromhex(h[0: 8])

@ -22,9 +22,11 @@ from coincurve.keys import (
PrivateKey) PrivateKey)
from basicswap.util import i2b, h2b from basicswap.util import i2b, h2b
from basicswap.util.integer import encode_varint, decode_varint
from basicswap.util.crypto import ripemd160, hash160 from basicswap.util.crypto import ripemd160, hash160
from basicswap.util.network import is_private_ip_address from basicswap.util.network import is_private_ip_address
from basicswap.util.rfc2440 import rfc2440_hash_password from basicswap.util.rfc2440 import rfc2440_hash_password
from basicswap.util_xmr import encode_address as xmr_encode_address
from basicswap.interface.btc import BTCInterface from basicswap.interface.btc import BTCInterface
from basicswap.interface.xmr import XMRInterface from basicswap.interface.xmr import XMRInterface
@ -347,6 +349,35 @@ class Test(unittest.TestCase):
assert (is_private_ip_address('20.87.245.0') is False) assert (is_private_ip_address('20.87.245.0') is False)
assert (is_private_ip_address('particl.io') is False) assert (is_private_ip_address('particl.io') is False)
def test_varint(self):
def test_case(i, expect_length):
b = encode_varint(i)
assert (len(b) == expect_length)
assert (decode_varint(b) == i)
test_case(0, 1)
test_case(1, 1)
test_case(127, 1)
test_case(128, 2)
test_case(253, 2)
test_case(8321, 2)
test_case(16383, 2)
test_case(16384, 3)
test_case(2097151, 3)
test_case(2097152, 4)
def test_base58(self):
kv = edu.get_secret()
Kv = edu.encodepoint(edf.scalarmult_B(kv))
ks = edu.get_secret()
Ks = edu.encodepoint(edf.scalarmult_B(ks))
addr = xmr_encode_address(Kv, Ks)
assert (addr.startswith('4'))
addr = xmr_encode_address(Kv, Ks, 4146)
assert (addr.startswith('Wo'))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

Loading…
Cancel
Save