mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-06 02:38:11 +01:00
Encode and decode Decred addresses.
This commit is contained in:
@@ -37,6 +37,9 @@ from basicswap.util.address import (
|
||||
decodeAddress,
|
||||
pubkeyToAddress,
|
||||
)
|
||||
from basicswap.util.crypto import (
|
||||
sha256,
|
||||
)
|
||||
from coincurve.keys import (
|
||||
PrivateKey,
|
||||
PublicKey)
|
||||
@@ -109,11 +112,27 @@ def find_vout_for_address_from_txobj(tx_obj, addr: str) -> int:
|
||||
raise RuntimeError("Vout not found for address: txid={}, addr={}".format(tx_obj['txid'], addr))
|
||||
|
||||
|
||||
class BTCInterface(CoinInterface):
|
||||
class Secp256k1Interface(CoinInterface):
|
||||
@staticmethod
|
||||
def curve_type():
|
||||
return Curves.secp256k1
|
||||
|
||||
def getNewSecretKey(self) -> bytes:
|
||||
return i2b(getSecretInt())
|
||||
|
||||
def getPubkey(self, privkey):
|
||||
return PublicKey.from_secret(privkey).format()
|
||||
|
||||
def verifyKey(self, k: bytes) -> bool:
|
||||
i = b2i(k)
|
||||
return (i < ep.o and i > 0)
|
||||
|
||||
def verifyPubkey(self, pubkey_bytes: bytes) -> bool:
|
||||
return verify_secp256k1_point(pubkey_bytes)
|
||||
|
||||
|
||||
class BTCInterface(Secp256k1Interface):
|
||||
|
||||
@staticmethod
|
||||
def coin_type():
|
||||
return Coins.BTC
|
||||
@@ -422,11 +441,11 @@ class BTCInterface(CoinInterface):
|
||||
return segwit_addr.encode(bech32_prefix, version, pkh)
|
||||
|
||||
def pkh_to_address(self, pkh: bytes) -> str:
|
||||
# pkh is hash160(pk)
|
||||
# pkh is ripemd160(sha256(pk))
|
||||
assert (len(pkh) == 20)
|
||||
prefix = self.chainparams_network()['pubkey_address']
|
||||
data = bytes((prefix,)) + pkh
|
||||
checksum = hashlib.sha256(hashlib.sha256(data).digest()).digest()
|
||||
checksum = sha256(sha256(data))
|
||||
return b58encode(data + checksum[0:4])
|
||||
|
||||
def sh_to_address(self, sh: bytes) -> str:
|
||||
@@ -452,12 +471,6 @@ class BTCInterface(CoinInterface):
|
||||
assert (len(pk) == 33)
|
||||
return self.pkh_to_address(hash160(pk))
|
||||
|
||||
def getNewSecretKey(self) -> bytes:
|
||||
return i2b(getSecretInt())
|
||||
|
||||
def getPubkey(self, privkey):
|
||||
return PublicKey.from_secret(privkey).format()
|
||||
|
||||
def getAddressHashFromKey(self, key: bytes) -> bytes:
|
||||
pk = self.getPubkey(key)
|
||||
return hash160(pk)
|
||||
@@ -465,13 +478,6 @@ class BTCInterface(CoinInterface):
|
||||
def getSeedHash(self, seed) -> bytes:
|
||||
return self.getAddressHashFromKey(seed)[::-1]
|
||||
|
||||
def verifyKey(self, k: bytes) -> bool:
|
||||
i = b2i(k)
|
||||
return (i < ep.o and i > 0)
|
||||
|
||||
def verifyPubkey(self, pubkey_bytes: bytes) -> bool:
|
||||
return verify_secp256k1_point(pubkey_bytes)
|
||||
|
||||
def encodeKey(self, key_bytes: bytes) -> str:
|
||||
wif_prefix = self.chainparams_network()['key_prefix']
|
||||
return toWIF(wif_prefix, key_bytes)
|
||||
@@ -1018,20 +1024,20 @@ class BTCInterface(CoinInterface):
|
||||
return hash160(K)
|
||||
|
||||
def getScriptDest(self, script):
|
||||
return CScript([OP_0, hashlib.sha256(script).digest()])
|
||||
return CScript([OP_0, sha256(script)])
|
||||
|
||||
def getScriptScriptSig(self, script: bytes) -> bytes:
|
||||
return bytes()
|
||||
|
||||
def getP2SHP2WSHDest(self, script):
|
||||
script_hash = hashlib.sha256(script).digest()
|
||||
script_hash = sha256(script)
|
||||
assert len(script_hash) == 32
|
||||
p2wsh_hash = hash160(CScript([OP_0, script_hash]))
|
||||
assert len(p2wsh_hash) == 20
|
||||
return CScript([OP_HASH160, p2wsh_hash, OP_EQUAL])
|
||||
|
||||
def getP2SHP2WSHScriptSig(self, script):
|
||||
script_hash = hashlib.sha256(script).digest()
|
||||
script_hash = sha256(script)
|
||||
assert len(script_hash) == 32
|
||||
return CScript([CScript([OP_0, script_hash, ]), ])
|
||||
|
||||
@@ -1249,25 +1255,25 @@ class BTCInterface(CoinInterface):
|
||||
return self.rpc_wallet('sendtoaddress', params)
|
||||
|
||||
def signCompact(self, k, message):
|
||||
message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
|
||||
message_hash = sha256(bytes(message, 'utf-8'))
|
||||
|
||||
privkey = PrivateKey(k)
|
||||
return privkey.sign_recoverable(message_hash, hasher=None)[:64]
|
||||
|
||||
def signRecoverable(self, k, message):
|
||||
message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
|
||||
message_hash = sha256(bytes(message, 'utf-8'))
|
||||
|
||||
privkey = PrivateKey(k)
|
||||
return privkey.sign_recoverable(message_hash, hasher=None)
|
||||
|
||||
def verifyCompactSig(self, K, message, sig):
|
||||
message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
|
||||
message_hash = sha256(bytes(message, 'utf-8'))
|
||||
pubkey = PublicKey(K)
|
||||
rv = pubkey.verify_compact(sig, message_hash, hasher=None)
|
||||
assert (rv is True)
|
||||
|
||||
def verifySigAndRecover(self, sig, message):
|
||||
message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
|
||||
message_hash = sha256(bytes(message, 'utf-8'))
|
||||
pubkey = PublicKey.from_signature_and_message(sig, message_hash, hasher=None)
|
||||
return pubkey.format()
|
||||
|
||||
@@ -1276,7 +1282,7 @@ class BTCInterface(CoinInterface):
|
||||
message_magic = self.chainparams()['message_magic']
|
||||
|
||||
message_bytes = SerialiseNumCompact(len(message_magic)) + bytes(message_magic, 'utf-8') + SerialiseNumCompact(len(message)) + bytes(message, 'utf-8')
|
||||
message_hash = hashlib.sha256(hashlib.sha256(message_bytes).digest()).digest()
|
||||
message_hash = sha256(sha256(message_bytes))
|
||||
signature_bytes = base64.b64decode(signature)
|
||||
rec_id = (signature_bytes[0] - 27) & 3
|
||||
signature_bytes = signature_bytes[1:] + bytes((rec_id,))
|
||||
@@ -1502,7 +1508,7 @@ class BTCInterface(CoinInterface):
|
||||
return CScript([OP_HASH160, script_hash, OP_EQUAL])
|
||||
|
||||
def get_p2wsh_script_pubkey(self, script: bytearray) -> bytearray:
|
||||
return CScript([OP_0, hashlib.sha256(script).digest()])
|
||||
return CScript([OP_0, sha256(script)])
|
||||
|
||||
def findTxnByHash(self, txid_hex: str):
|
||||
# Only works for wallet txns
|
||||
|
||||
63
basicswap/interface/dcr.py
Normal file
63
basicswap/interface/dcr.py
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- 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.
|
||||
|
||||
from basicswap.chainparams import Coins
|
||||
from basicswap.interface.btc import Secp256k1Interface
|
||||
from basicswap.util.address import (
|
||||
b58decode,
|
||||
b58encode,
|
||||
)
|
||||
from basicswap.util.crypto import (
|
||||
blake256,
|
||||
ripemd160,
|
||||
)
|
||||
|
||||
|
||||
class DCRInterface(Secp256k1Interface):
|
||||
|
||||
@staticmethod
|
||||
def coin_type():
|
||||
return Coins.DCR
|
||||
|
||||
@staticmethod
|
||||
def exp() -> int:
|
||||
return 8
|
||||
|
||||
@staticmethod
|
||||
def COIN() -> int:
|
||||
return 100000000
|
||||
|
||||
@staticmethod
|
||||
def nbk() -> int:
|
||||
return 32
|
||||
|
||||
@staticmethod
|
||||
def nbK() -> int: # No. of bytes requires to encode a public key
|
||||
return 33
|
||||
|
||||
def __init__(self, coin_settings, network, swap_client=None):
|
||||
super().__init__(network)
|
||||
|
||||
def pkh(self, pubkey: bytes) -> bytes:
|
||||
return ripemd160(blake256(pubkey))
|
||||
|
||||
def pkh_to_address(self, pkh: bytes) -> str:
|
||||
prefix = self.chainparams_network()['pubkey_address']
|
||||
|
||||
data = prefix.to_bytes(2, 'big') + pkh
|
||||
checksum = blake256(blake256(data))
|
||||
return b58encode(data + checksum[0:4])
|
||||
|
||||
def decode_address(self, address: str) -> bytes:
|
||||
addr_data = b58decode(address)
|
||||
if addr_data is None:
|
||||
return None
|
||||
prefixed_data = addr_data[:-4]
|
||||
checksum = addr_data[-4:]
|
||||
if blake256(blake256(prefixed_data))[:4] != checksum:
|
||||
raise ValueError('Checksum mismatch')
|
||||
return prefixed_data
|
||||
Reference in New Issue
Block a user