Skip to content

Commit

Permalink
SFT-1708: first pass at taproot address verification, incorrect public
Browse files Browse the repository at this point in the history
key generating
  • Loading branch information
mjg-foundation committed Sep 18, 2023
1 parent 976e397 commit 88be495
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 4 deletions.
4 changes: 4 additions & 0 deletions extmod/foundation/modtcc-codecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ STATIC mp_obj_t modtcc_bech32_encode(size_t n_args, const mp_obj_t *args) {
const uint32_t segwit_version = mp_obj_int_get_checked(args[1]);
uint32_t bech32_version = BECH32_ENCODING_BECH32;

if (segwit_version > 0) {
bech32_version = BECH32_ENCODING_BECH32M;
}

if (n_args == 4) {
bech32_version = mp_obj_int_get_checked(args[3]);
}
Expand Down
4 changes: 3 additions & 1 deletion ports/stm32/boards/Passport/modules/chains.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import trezorcrypto
import tcc
from public_constants import AF_CLASSIC, AF_P2SH, AF_P2WPKH, AF_P2WSH, AF_P2WPKH_P2SH, AF_P2WSH_P2SH
from public_constants import AFC_PUBKEY, AFC_SEGWIT, AFC_BECH32, AFC_SCRIPT, AFC_WRAPPED
from public_constants import AFC_PUBKEY, AFC_SEGWIT, AFC_BECH32, AFC_SCRIPT, AFC_WRAPPED, AFC_BECH32M
from serializations import hash160, ser_compact_size
from ucollections import namedtuple
from opcodes import OP_CHECKMULTISIG
Expand Down Expand Up @@ -116,6 +116,8 @@ def address(cls, node, addr_fmt):
if addr_fmt & AFC_BECH32:
# bech32 encoded segwit p2pkh
return tcc.codecs.bech32_encode(cls.bech32_hrp, 0, raw)
elif addr_fmt & AFC_BECH32M:
return tcc.codecs.bech32_encode(cls.bech32_hrp, 1, raw)

# see bip-141, "P2WPKH nested in BIP16 P2SH" section
assert addr_fmt == AF_P2WPKH_P2SH
Expand Down
3 changes: 3 additions & 0 deletions ports/stm32/boards/Passport/modules/public_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
AFC_BECH32 = const(0x04) # just how we're encoding it?
AFC_SCRIPT = const(0x08) # paying into a script
AFC_WRAPPED = const(0x10) # for transition/compat types for segwit vs. old
AFC_BECH32M = const(0x20) # bech32m encoding

# Numeric codes for specific address types
AF_CLASSIC = AFC_PUBKEY # 1addr
Expand All @@ -58,6 +59,7 @@
AF_P2WSH = AFC_SCRIPT | AFC_SEGWIT | AFC_BECH32 # segwit multisig
AF_P2WPKH_P2SH = AFC_WRAPPED | AFC_PUBKEY | AFC_SEGWIT # looks classic P2SH, but p2wpkh inside
AF_P2WSH_P2SH = AFC_WRAPPED | AFC_SCRIPT | AFC_SEGWIT # looks classic P2SH, segwit multisig
AF_P2TR = AFC_PUBKEY | AFC_SEGWIT | AFC_BECH32M # taproot allows scripts and pubkeys

SUPPORTED_ADDR_FORMATS = frozenset([
AF_CLASSIC,
Expand All @@ -66,6 +68,7 @@
AF_P2WSH,
AF_P2WPKH_P2SH,
AF_P2WSH_P2SH,
AF_P2TR,
])

# BIP-174 aka PSBT defined values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ async def search_for_address_task(
import stash
from errors import Error
from uasyncio import sleep_ms
from ubinascii import hexlify as b2a_hex

try:
with stash.SensitiveValues() as sv:
Expand All @@ -50,9 +51,11 @@ async def search_for_address_task(
addr_path = '{}/{}/{}'.format(path, is_change, curr_idx) # Zero for non-change address
# print('Singlesig: addr_path={}'.format(addr_path))
node = sv.derive_path(addr_path)
print(b2a_hex(node.public_key()))
curr_address = sv.chain.address(node, addr_type)
# print(' curr_idx={}: path={} addr_type={} curr_address = {}'.format(curr_idx, addr_path,
# addr_type, curr_address))
print("path: {}, address: {}".format(addr_path, curr_address))
if curr_address == address:
await on_done(curr_idx, addr_path, None)
return
Expand Down
18 changes: 15 additions & 3 deletions ports/stm32/boards/Passport/modules/wallets/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import chains
import common
from public_constants import AF_CLASSIC, AF_P2SH, AF_P2WPKH_P2SH, AF_P2WSH_P2SH, AF_P2WPKH, AF_P2WSH
from public_constants import AF_CLASSIC, AF_P2SH, AF_P2WPKH_P2SH, AF_P2WSH_P2SH, AF_P2WPKH, AF_P2WSH, AF_P2TR
from utils import get_accounts, get_derived_keys


Expand Down Expand Up @@ -73,7 +73,10 @@ def get_addr_type_from_address(address, is_multisig):
return AF_P2WSH_P2SH if is_multisig else AF_P2WPKH_P2SH
elif (address[0] == 'b' and address[1] == 'c' and address[2] == '1') or \
(address[0] == 't' and address[1] == 'b' and address[2] == '1'):
return AF_P2WSH if is_multisig else AF_P2WPKH
if address[3] == 'p':
return AF_P2TR
else:
return AF_P2WSH if is_multisig else AF_P2WPKH

return None

Expand All @@ -91,6 +94,8 @@ def get_bip_num_from_addr_type(addr_type, is_multisig):
return 84
elif addr_type == AF_P2WPKH_P2SH:
return 49
elif addr_type == AF_P2TR:
return 86
else:
raise ValueError(addr_type)

Expand All @@ -110,6 +115,8 @@ def get_addr_type_from_deriv(path):
return AF_P2WSH_P2SH
elif subpath == '2':
return AF_P2WSH
elif type_str == '86':
return AF_P2TR

return None

Expand All @@ -133,7 +140,10 @@ def get_deriv_fmt_from_address(address, is_multisig):
return "m/49'/{coin_type}'/{acct}'"
elif ((address[0] == 'b' and address[1] == 'c' and address[2] == '1') or
(address[0] == 't' and address[1] == 'b' and address[2] == '1')):
return "m/84'/{coin_type}'/{acct}'"
if address[3] == 'p':
return "m/86'/{coin_type}'/{acct}'"
else:
return "m/84'/{coin_type}'/{acct}'"

return None

Expand All @@ -154,6 +164,8 @@ def get_deriv_fmt_from_addr_type(addr_type, is_multisig):
return "m/49'/{coin_type}'/{acct}'"
elif addr_type == AF_P2WPKH:
return "m/84'/{coin_type}'/{acct}'"
elif addr_type == AF_P2TR:
return "m/86'/{coin_type}'/{acct}'"

return None

Expand Down

0 comments on commit 88be495

Please sign in to comment.