Host-customized fork of https://github.com/tecnovert/basicswap/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
3.4 KiB

# -*- coding: utf-8 -*-
# Copyright (c) 2022-2024 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
from basicswap.contrib.segwit_addr import bech32_decode, convertbits, bech32_encode
from basicswap.util.crypto import ripemd160, sha256
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
def b58decode(v, length=None):
long_value = 0
for (i, c) in enumerate(v[::-1]):
ofs = __b58chars.find(c)
if ofs < 0:
return None
long_value += ofs * (58**i)
result = bytes()
while long_value >= 256:
div, mod = divmod(long_value, 256)
result = bytes((mod,)) + result
long_value = div
result = bytes((long_value,)) + result
nPad = 0
for c in v:
if c == __b58chars[0]:
nPad += 1
else:
break
pad = bytes((0,)) * nPad
result = pad + result
if length is not None and len(result) != length:
return None
return result
def b58encode(v):
long_value = 0
for (i, c) in enumerate(v[::-1]):
long_value += (256**i) * c
result = ''
while long_value >= 58:
div, mod = divmod(long_value, 58)
result = __b58chars[mod] + result
long_value = div
result = __b58chars[long_value] + result
# leading 0-bytes in the input become leading-1s
nPad = 0
for c in v:
if c == 0:
nPad += 1
else:
break
return (__b58chars[0] * nPad) + result
def encodeStealthAddress(prefix_byte: int, scan_pubkey: bytes, spend_pubkey: bytes) -> str:
data = bytes((0x00,))
data += scan_pubkey
data += bytes((0x01,))
data += spend_pubkey
data += bytes((0x00,)) # number_signatures - unused
data += bytes((0x00,)) # num prefix bits
b = bytes((prefix_byte,)) + data
b += sha256(sha256(b))[:4]
return b58encode(b)
def decodeWif(encoded_key: str) -> bytes:
key = b58decode(encoded_key)[1:-4]
if len(key) == 33:
return key[:-1]
return key
def toWIF(prefix_byte: int, b: bytes, compressed: bool = True) -> str:
b = bytes((prefix_byte,)) + b
if compressed:
b += bytes((0x01,))
b += sha256(sha256(b))[:4]
return b58encode(b)
def getKeyID(key_data: bytes) -> bytes:
return ripemd160(sha256(key_data))
def bech32Decode(hrp: str, addr: str) -> bytes:
hrpgot, data = bech32_decode(addr)
if hrpgot != hrp:
return None
decoded = convertbits(data, 5, 8, False)
if decoded is None or len(decoded) < 2 or len(decoded) > 40:
return None
return bytes(decoded)
def bech32Encode(hrp: str, data: bytes) -> str:
ret = bech32_encode(hrp, convertbits(data, 8, 5))
if bech32Decode(hrp, ret) is None:
return None
return ret
def decodeAddress(address: str) -> bytes:
addr_data = b58decode(address)
if addr_data is None:
return None
prefixed_data = addr_data[:-4]
checksum = addr_data[-4:]
if sha256(sha256(prefixed_data))[:4] != checksum:
raise ValueError('Checksum mismatch')
return prefixed_data
def encodeAddress(address: bytes) -> str:
checksum = sha256(sha256(address))
return b58encode(address + checksum[0:4])
def pubkeyToAddress(prefix: int, pubkey: bytes) -> str:
return encodeAddress(bytes((prefix,)) + getKeyID(pubkey))