Skip to content

Commit

Permalink
Dev v1.0.8 (#76)
Browse files Browse the repository at this point in the history
* PASS1-82: Delete input PSBT file after successful signing (#59)

* PASS1-156: Bitcoin Core causes invalid bitcoin address error (#63)

* PASS1-126: Passport crashes when making a microSD backup (#71)

This issue was happening only when attempting to backup a device with a multisig configuration that contained multiple different derivation paths instead of all devices in a given configuration having the same derivation path.

* PASS1-181: Passport fails to verify multi-sig change addresses in Sparrow (#72)

* PASS1-191: Add pairing support for Simple Bitcoin Wallet (#75)

Co-authored-by: Corey Lakey <corey.lakey@gmail.com>
Co-authored-by: Corey Lakey <corey@foundationdevices.com>
  • Loading branch information
3 people committed Dec 29, 2021
1 parent 3c27b48 commit 4268b2e
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 7 deletions.
4 changes: 2 additions & 2 deletions ports/stm32/boards/Passport/manifest.py
Expand Up @@ -11,7 +11,7 @@
'menu.py', 'settings.py', 'sram4.py', 'sffile.py', 'collections/deque.py', 'uQR.py', 'constants.py',
'callgate.py', 'pincodes.py', 'stash.py', 'login_ux.py', 'public_constants.py', 'seed.py', 'chains.py',
'opcodes.py', 'bip39_utils.py', 'seed_entry_ux.py', 'sflash.py', 'snake.py', 'stacking_sats.py',
'se_commands.py', 'serializations.py','seed_check_ux.py', 'export.py', 'compat7z.py', 'multisig.py', 'psbt.py',
'se_commands.py', 'serializations.py', 'seed_check_ux.py', 'export.py', 'compat7z.py', 'multisig.py', 'psbt.py',
'periodic.py', 'exceptions.py', 'noise_source.py', 'self_test_ux.py', 'flash_cache.py',
'history.py', 'accounts.py', 'log.py', 'descriptor.py', 'accept_terms_ux.py', 'new_wallet.py', 'stat.py',
'uasyncio/__init__.py', 'uasyncio/core.py', 'uasyncio/queues.py', 'uasyncio/synchro.py', 'ie.py',
Expand All @@ -33,4 +33,4 @@
'wallets/multisig_json.py', 'wallets/multisig_import.py', 'wallets/generic_json_wallet.py', 'wallets/sparrow.py',
'wallets/bitcoin_core.py', 'wallets/wasabi.py', 'wallets/btcpay.py', 'wallets/gordian.py', 'wallets/lily.py',
'wallets/fullynoded.py', 'wallets/dux_reserve.py', 'wallets/specter.py', 'wallets/casa.py', 'wallets/vault.py',
'wallets/caravan.py'))
'wallets/caravan.py', 'wallets/simple_bitcoin_wallet.py'))
3 changes: 2 additions & 1 deletion ports/stm32/boards/Passport/modules/actions.py
Expand Up @@ -21,7 +21,7 @@
import common
from common import settings, system, noise, dis
from utils import (UXStateMachine, imported, pretty_short_delay, xfp2str, to_str,
truncate_string_to_width, set_next_addr, scan_for_address, get_accounts, run_chooser,
truncate_string_to_width, set_next_addr, get_accounts, run_chooser,
make_account_name_num, is_valid_address, save_next_addr, needs_microsd, format_btc_address,
is_all_zero, bytes_to_hex_str, split_to_lines, is_valid_btc_address, do_address_verify, run_chooser)
from wallets.utils import get_export_mode, get_addr_type_from_address, get_deriv_path_from_addr_type_and_acct
Expand Down Expand Up @@ -272,6 +272,7 @@ async def show(self):
if address == None:
return

address = address.lower()
address, is_valid_btc = await is_valid_btc_address(address)
if is_valid_btc == False:
if not self.goto_prev():
Expand Down
4 changes: 3 additions & 1 deletion ports/stm32/boards/Passport/modules/auth.py
Expand Up @@ -684,7 +684,7 @@ def sign_transaction(psbt_len, flags=0x0, psbt_sha=None):

def sign_psbt_file(filename):
# sign a PSBT file found on a microSD card
from files import CardSlot, CardMissingError
from files import CardSlot, CardMissingError, securely_blank_file
from common import dis, system
# from sram4 import tmp_buf -- the fd.readinto() below doesn't work for some odd reason, even though the fd.readinto() for firmware updates
tmp_buf = bytearray(1024)
Expand Down Expand Up @@ -798,6 +798,8 @@ async def done(psbt):
# save transaction, in hex
txid = psbt.finalize(fd)

securely_blank_file(filename)

# success and done!
break

Expand Down
Expand Up @@ -15,7 +15,7 @@ class PsbtTxnSampler(DataSampler):
# Return True if it matches or False if not.
@classmethod
def sample(cls, data):
print('psbt sampler: data={}'.format(b2a_hex(data)))
# print('psbt sampler: data={}'.format(b2a_hex(data)))
if data[0:5] == b'psbt\xff':
return True
if data[0:10] == b'70736274ff': # hex-encoded
Expand Down
2 changes: 1 addition & 1 deletion ports/stm32/boards/Passport/modules/export.py
Expand Up @@ -40,7 +40,7 @@ def ms_has_master_xfp(xpubs):
master_xfp = settings.get('xfp', None)

for xpub in xpubs:
(xfp, _) = xpub
xfp = xpub[0]
# print('ms_has_master_xfp: xfp={} master_xfp={}'.format(xfp, master_xfp))
if xfp == master_xfp:
# print('Including this one')
Expand Down
38 changes: 38 additions & 0 deletions ports/stm32/boards/Passport/modules/files.py
Expand Up @@ -246,4 +246,42 @@ def get_file_path(self, filename, path=None):

return fname, basename+ext

def securely_blank_file(full_path):
# input PSBT file no longer required; so delete it
# - blank with zeros
# - rename to garbage (to hide filename after undelete)
# - delete
# - ok if file missing already (card maybe have been swapped)
#
# NOTE: we know the FAT filesystem code is simple, see
# ../external/micropython/extmod/vfs_fat.[ch]

path, basename = full_path.rsplit('/', 1)

with CardSlot() as card:
try:
blk = bytes(64)

with open(full_path, 'r+b') as fd:
size = fd.seek(0, 2)
fd.seek(0)

# blank it
for i in range((size // len(blk)) + 1):
fd.write(blk)

assert fd.seek(0, 1) >= size

# probably pointless, but why not:
os.sync()

except OSError as exc:
# missing file is okay
if exc.args[0] == ENOENT: return
raise

# rename it and delete
new_name = path + '/' + ('x'*len(basename))
os.rename(full_path, new_name)
os.remove(new_name)
# EOF
3 changes: 2 additions & 1 deletion ports/stm32/boards/Passport/modules/utils.py
Expand Up @@ -447,6 +447,7 @@ async def show_top_menu():
# TODO: For now this just checks the front bytes, but it could ensure the whole thing is valid
def is_valid_address(address):
# Valid addresses: 1 , 3 , bc1, tb1, m, n, 2
address = address.lower()
return (len(address) > 3) and \
((address[0] == '1') or \
(address[0] == '2') or \
Expand Down Expand Up @@ -530,7 +531,7 @@ def find_address(path, start_address_idx, address, addr_type, ms_wallet, is_chan
with stash.SensitiveValues() as sv:
if ms_wallet:
# NOTE: Can't easily reverse order here, so this is slightly less efficient
for (curr_idx, paths, curr_address, script) in ms_wallet.yield_addresses(start_address_idx, max_to_check):
for (curr_idx, paths, curr_address, script) in ms_wallet.yield_addresses(start_address_idx, max_to_check, change_idx=1 if is_change else 0):
# print('curr_idx={}: paths={} curr_address = {}'.format(curr_idx, paths, curr_address))

if curr_address == address:
Expand Down
@@ -0,0 +1,21 @@
# SPDX-FileCopyrightText: 2021 Foundation Devices, Inc. <hello@foundationdevices.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# simple_bitcoin_wallet.py - Simple Bitcoin Wallet support
#

from .generic_json_wallet import create_generic_json_wallet
from .multisig_json import create_multisig_json_wallet
from .multisig_import import read_multisig_config_from_qr, read_multisig_config_from_microsd
from data_codecs.qr_type import QRType

SimpleBitcoinWallet = {
'label': 'Simple Bitcoin Wallet',
'sig_types': [
{'id': 'single-sig', 'label': 'Single-sig', 'addr_type': None,
'create_wallet': create_generic_json_wallet},
],
'export_modes': [
{'id': 'qr', 'label': 'QR Code', 'qr_type': QRType.UR2},
]
}
2 changes: 2 additions & 0 deletions ports/stm32/boards/Passport/modules/wallets/sw_wallets.py
Expand Up @@ -15,6 +15,7 @@
# from .fullynoded import FullyNodedWallet
# from .gordian import GordianWallet
# from .lily import LilyWallet
from .simple_bitcoin_wallet import SimpleBitcoinWallet
from .sparrow import SparrowWallet
from .specter import SpecterWallet
from .wasabi import WasabiWallet
Expand All @@ -31,6 +32,7 @@
# FullyNodedWallet,
# GordianWallet,
# LilyWallet,
SimpleBitcoinWallet,
SparrowWallet,
SpecterWallet,
WasabiWallet,
Expand Down

0 comments on commit 4268b2e

Please sign in to comment.