parent
65481308e6
commit
7de6a082d3
@ -0,0 +1,84 @@
|
||||
from micropython import const
|
||||
|
||||
from trezor.crypto.hashlib import sha256, ripemd160
|
||||
from trezor.crypto import base58, bech32
|
||||
from trezor.utils import ensure
|
||||
|
||||
from trezor.messages.CoinType import CoinType
|
||||
from trezor.messages import FailureType
|
||||
from trezor.messages import InputScriptType
|
||||
|
||||
# supported witness version for bech32 addresses
|
||||
_BECH32_WITVER = const(0x00)
|
||||
|
||||
|
||||
class AddressError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_address(script_type: InputScriptType, coin: CoinType, node) -> bytes:
|
||||
|
||||
if script_type == InputScriptType.SPENDADDRESS: # p2pkh
|
||||
return node.address(coin.address_type)
|
||||
|
||||
elif script_type == InputScriptType.SPENDWITNESS: # native p2wpkh
|
||||
if not coin.segwit or not coin.bech32_prefix:
|
||||
raise AddressError(FailureType.ProcessError,
|
||||
'Segwit not enabled on this coin')
|
||||
return address_p2wpkh(node.public_key(), coin.bech32_prefix)
|
||||
|
||||
elif script_type == InputScriptType.SPENDP2SHWITNESS: # p2wpkh using p2sh
|
||||
if not coin.segwit or not coin.address_type_p2sh:
|
||||
raise AddressError(FailureType.ProcessError,
|
||||
'Segwit not enabled on this coin')
|
||||
return address_p2wpkh_in_p2sh(node.public_key(), coin.address_type_p2sh)
|
||||
|
||||
else:
|
||||
raise AddressError(FailureType.ProcessError,
|
||||
'Invalid script type')
|
||||
|
||||
|
||||
def address_p2wpkh_in_p2sh(pubkey: bytes, addrtype: int) -> str:
|
||||
s = bytearray(21)
|
||||
s[0] = addrtype
|
||||
s[1:21] = address_p2wpkh_in_p2sh_raw(pubkey)
|
||||
return base58.encode_check(bytes(s))
|
||||
|
||||
|
||||
def address_p2wpkh_in_p2sh_raw(pubkey: bytes) -> bytes:
|
||||
s = bytearray(22)
|
||||
s[0] = 0x00 # OP_0
|
||||
s[1] = 0x14 # pushing 20 bytes
|
||||
s[2:22] = ecdsa_hash_pubkey(pubkey)
|
||||
h = sha256(s).digest()
|
||||
h = ripemd160(h).digest()
|
||||
return h
|
||||
|
||||
|
||||
def address_p2wpkh(pubkey: bytes, hrp: str) -> str:
|
||||
pubkeyhash = ecdsa_hash_pubkey(pubkey)
|
||||
address = bech32.encode(hrp, _BECH32_WITVER, pubkeyhash)
|
||||
if address is None:
|
||||
raise AddressError(FailureType.ProcessError,
|
||||
'Invalid address')
|
||||
return address
|
||||
|
||||
|
||||
def decode_bech32_address(prefix: str, address: str) -> bytes:
|
||||
witver, raw = bech32.decode(prefix, address)
|
||||
if witver != _BECH32_WITVER:
|
||||
raise AddressError(FailureType.ProcessError,
|
||||
'Invalid address witness program')
|
||||
return bytes(raw)
|
||||
|
||||
|
||||
def ecdsa_hash_pubkey(pubkey: bytes) -> bytes:
|
||||
if pubkey[0] == 0x04:
|
||||
ensure(len(pubkey) == 65) # uncompressed format
|
||||
elif pubkey[0] == 0x00:
|
||||
ensure(len(pubkey) == 1) # point at infinity
|
||||
else:
|
||||
ensure(len(pubkey) == 33) # compresssed format
|
||||
h = sha256(pubkey).digest()
|
||||
h = ripemd160(h).digest()
|
||||
return h
|
Loading…
Reference in new issue