Browse Source

Merge pull request #12 from Foundation-Devices/dev-1.0.5

v1.0.5 changes
PASS1-98_PASS1-114 v1.0.5
Ken Carpenter 4 years ago
committed by GitHub
parent
commit
1d84e88492
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      .githooks/pre-commit
  2. 8
      ports/stm32/boards/Passport/modules/actions.py
  3. 9
      ports/stm32/boards/Passport/modules/auth.py
  4. 1
      ports/stm32/boards/Passport/modules/common.py
  5. 2
      ports/stm32/boards/Passport/modules/constants.py
  6. 2
      ports/stm32/boards/Passport/modules/data_codecs/data_decoder.py
  7. 3
      ports/stm32/boards/Passport/modules/data_codecs/qr_codec.py
  8. 6
      ports/stm32/boards/Passport/modules/data_codecs/ur1_codec.py
  9. 21
      ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py
  10. 15
      ports/stm32/boards/Passport/modules/psbt.py
  11. 6
      ports/stm32/boards/Passport/modules/sflash.py
  12. 10
      ports/stm32/boards/Passport/modules/ur2/ur_decoder.py
  13. 14
      ports/stm32/boards/Passport/modules/ur2/utils.py
  14. 6
      ports/stm32/boards/Passport/modules/ux.py
  15. 4
      ports/stm32/boards/Passport/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h

16
.githooks/pre-commit

@ -0,0 +1,16 @@
#!/bin/bash
RESULTS=$(find . -name '*.py' -exec grep -H fake_it[\ ]*=[\ ]*True {} +)
LEN=`expr length "$RESULTS"`
echo $RESULTS
# echo $LEN
if [[ $LEN -gt 0 ]]; then
echo
echo "======================================================"
echo "ERROR: Never commit code with fake seeds or passwords!"
echo "======================================================"
exit 1
else
exit 0
fi

8
ports/stm32/boards/Passport/modules/actions.py

@ -14,6 +14,7 @@
import pyb
import version
import gc
from files import CardMissingError, CardSlot
# import main
from uasyncio import sleep_ms
@ -1356,11 +1357,18 @@ async def handle_psbt_data_format(data):
try:
from auth import sign_psbt_buf
gc.collect()
# print('Available RAM: psbt 1 = {}'.format(gc.mem_free()))
# The data can be a string or may already be a bytes object
if isinstance(data, bytes):
data_buf = data
else:
data_buf = bytes(data, 'utf-8')
gc.collect() # Try to avoid excessive fragmentation
# print('Available RAM: psbt 2 = {}'.format(gc.mem_free()))
# print("data_buf={}".format(data_buf))
system.show_busy_bar()
dis.fullscreen('Analyzing...')

9
ports/stm32/boards/Passport/modules/auth.py

@ -905,7 +905,7 @@ async def sign_psbt_buf(psbt_buf):
# Create a new BytesIO() to hold the result
async def done(psbt):
from common import system, last_scanned_qr_type
from common import system, last_scanned_qr_type, last_scanned_ur_prefix
system.hide_busy_bar()
signed_bytes = None
with BytesIO() as bfd:
@ -928,13 +928,16 @@ async def sign_psbt_buf(psbt_buf):
# print('last_scanned_qr_type={}'.format(last_scanned_qr_type))
# Text format for UR1, but binary for UR2
o = DisplayURCode('Signed Txn', signed_bytes if last_scanned_qr_type == QRType.UR2 else signed_hex, last_scanned_qr_type or QRType.UR2, None, is_binary=True)
# def __init__(self, title, qr_text, qr_type, qr_args=None, msg=None, left_btn='DONE', right_btn='RESIZE', is_binary=False):
o = DisplayURCode('Signed Txn', signed_bytes if last_scanned_qr_type == QRType.UR2 else signed_hex, last_scanned_qr_type or QRType.UR2, {'prefix': last_scanned_ur_prefix }, is_binary=True)
result = await o.interact_bare()
UserAuthorizedAction.cleanup()
UserAuthorizedAction.active_request = ApproveTransaction(psbt_len, approved_cb=done)
# kill any menu stack, and put our thing at the top
# Kill any menu stack, and put our thing at the top - whatever async chain started off this signing process will
# now resume and complete, and then the following action will become active.
abort_and_goto(UserAuthorizedAction.active_request)

1
ports/stm32/boards/Passport/modules/common.py

@ -66,3 +66,4 @@ is_new_wallet_a_duplicate = False
# The QRTYpe of the last QR code that was scanned
last_scanned_qr_type = None
last_scanned_ur_prefix = None

2
ports/stm32/boards/Passport/modules/constants.py

@ -27,7 +27,7 @@ FLASH_CACHE_CHECKSUM_SIZE = 32
FLASH_CACHE_MAX_JSON_LEN = FLASH_CACHE_BLOCK_SIZE - FLASH_CACHE_CHECKSUM_SIZE
# Flash usage for PSBT signing
PSBT_MAX_SIZE = (SPI_FLASH_TOTAL_SIZE - FLASH_CACHE_TOTAL_SIZE) // 2
PSBT_MAX_SIZE = (SPI_FLASH_TOTAL_SIZE - FLASH_CACHE_TOTAL_SIZE) # Total size available for both input and output
# Flash firmware constants
FW_MAX_SIZE = SPI_FLASH_TOTAL_SIZE - FLASH_CACHE_TOTAL_SIZE

2
ports/stm32/boards/Passport/modules/data_codecs/data_decoder.py

@ -29,7 +29,7 @@ class DataDecoder:
def get_error(self):
return None
def get_type(self):
def get_ur_prefix(self):
return None
def decode(self):

3
ports/stm32/boards/Passport/modules/data_codecs/qr_codec.py

@ -30,6 +30,9 @@ class QRDecoder(DataDecoder):
def get_error(self):
return None
def get_ur_prefix(self):
return None
def decode(self):
return self.data

6
ports/stm32/boards/Passport/modules/data_codecs/ur1_codec.py

@ -44,8 +44,8 @@ class UR1Decoder(DataDecoder):
def get_error(self):
return self.error
def get_type(self):
return self.decoder.expected_type()
def get_ur_prefix(self):
return 'bytes' # TODO: Get the type from the UR1 decoder
def decode(self):
from common import system
@ -112,7 +112,7 @@ class UR1Sampler(DataSampler):
# Return True if it matches or False if not
@classmethod
def sample(cls, data):
r = re.compile('^ur:bytes/(\d)+of(\d)+/')
r = re.compile('^ur:bytes/') # Don't look for the n of m count anymore
m = r.match(data.lower())
return m != None

21
ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py

@ -49,7 +49,7 @@ class UR2Decoder(DataDecoder):
else:
return None
def get_type(self):
def get_ur_prefix(self):
return self.decoder.expected_type()
def decode(self):
@ -69,9 +69,13 @@ class UR2Decoder(DataDecoder):
return QRType.UR2
class UR2Encoder(DataEncoder):
def __init__(self, _args):
def __init__(self, args):
self.qr_sizes = [280, 100, 70]
self.type = None
if isinstance(args, dict):
self.prefix = args['prefix'] or 'bytes'
else:
self.prefix = 'bytes'
def get_num_supported_sizes(self):
return len(self.qr_sizes)
@ -87,7 +91,7 @@ class UR2Encoder(DataEncoder):
# print('UR2: data={}'.format(to_str(data)))
encoder.encodeBytes(data)
# TODO: Need to change this interface most likely to allow for different types like crypto-psbt
ur_obj = UR("bytes", encoder.get_bytes())
ur_obj = UR(self.prefix, encoder.get_bytes())
self.ur_encoder = UREncoder(ur_obj, max_fragment_len)
# UR2.0's next_part() returns the initial pieces split into max_fragment_len bytes, but then switches over to
@ -104,9 +108,14 @@ class UR2Sampler(DataSampler):
# Return True if it matches or False if not
@classmethod
def sample(cls, data):
r = re.compile('^ur:[a-z\d-]+\/(\d)+-(\d)+\/')
m = r.match(data.lower())
return m != None
try:
# Rather than try a complex regex here, we just let the decoder try to decode and if it fails.
# it must not be UR2.
decoder = URDecoder()
result = decoder.receive_part(data)
return result
except e:
return False
# Number of bytes required to successfully recognize this format
@classmethod

15
ports/stm32/boards/Passport/modules/psbt.py

@ -1392,16 +1392,31 @@ class psbtObject(psbtProxy):
for k in self.unknown:
wr(k[0], self.unknown[k], k[1:])
# import micropython
# print('======================================')
# micropython.mem_info(1)
# print('======================================')
# sep between globals and inputs
out_fd.write(b'\0')
for idx, inp in enumerate(self.inputs):
# print('Input {}: free mem={}'.format(idx, gc.mem_free()))
inp.serialize(out_fd, idx)
out_fd.write(b'\0')
gc.collect() # Give collector a chance to run to help avoid fragmentation
for idx, outp in enumerate(self.outputs):
# print('Output {}: free mem={}'.format(idx, gc.mem_free()))
outp.serialize(out_fd, idx)
out_fd.write(b'\0')
gc.collect() # Give collector a chance to run to help avoid fragmentation
# print('After serialize(): free mem={}'.format(gc.mem_free()))
# print('======================================')
# micropython.mem_info(1)
# print('======================================')
def sign_it(self):
# txn is approved. sign all inputs we can sign. add signatures

6
ports/stm32/boards/Passport/modules/sflash.py

@ -15,10 +15,10 @@
# - it wants to waste 4k on a buffer
#
# Layout for project:
# - 768 PSBT incoming (MAX_TXN_LEN)
# - 768 PSBT outgoing (MAX_TXN_LEN)
# - 917K PSBT incoming (MAX_TXN_LEN)
# - 917K PSBT outgoing (MAX_TXN_LEN)
# - The previous two regions are only used when signing PSBTs.
# - The same space is used to hold firmware updates.
# - The same space is also used to hold firmware updates.
# - 256k flash cache - similar to settings, but for UTXOs and wallet address cache
#
import machine

10
ports/stm32/boards/Passport/modules/ur2/ur_decoder.py

@ -34,7 +34,7 @@ class InvalidFragment(Exception):
class URDecoder:
def __init__(self):
self.fountain_decoder = FountainDecoder()
self.expected_type = None
self._expected_type = None
self.result = None
@staticmethod
@ -93,13 +93,13 @@ class URDecoder:
raise InvalidSequenceComponent()
def validate_part(self, type):
if self.expected_type == None:
if self._expected_type == None:
if not is_ur_type(type):
return False
self.expected_type = type
self._expected_type = type
return True
else:
return type == self.expected_type
return type == self._expected_type
def receive_part(self, str):
try:
@ -148,7 +148,7 @@ class URDecoder:
return False
def expected_type(self):
return self.expected_type
return self._expected_type
def expected_part_count(self):
return self.fountain_decoder.expected_part_count()

14
ports/stm32/boards/Passport/modules/ur2/utils.py

@ -33,14 +33,12 @@ def string_to_bytes(s):
return bytes(s, 'utf8')
def is_ur_type(ch):
if 'a' <= ch and ch <= 'z':
return True
if '0' <= ch and ch <= '9':
return True
if ch == '-':
return True
return False
def is_ur_type(type):
for ch in type:
if not (ch >= 'a' and ch <= 'z') and not(ch >= '0' and ch <= '9') and ch != '-':
return False
return True
def partition(s, n):

6
ports/stm32/boards/Passport/modules/ux.py

@ -1180,9 +1180,9 @@ class DisplayURCode(UserInteraction):
return 250
def render_qr(self, data):
from utils import imported
from utils import imported, bytes_to_hex_str
# print('data: {}'.format(data))
# print('data: {}'.format(bytes_to_hex_str(data)))
if self.last_render_id != self.render_id:
self.last_render_id = self.render_id
@ -1488,7 +1488,9 @@ async def ux_scan_qr_code(title):
# Set the last QRType so that signed transactions know what to encode as
common.last_scanned_qr_type = qr_decoder.get_data_format()
common.last_scanned_ur_prefix = qr_decoder.get_ur_prefix()
# print('common.last_scanned_qr_type={}'.format(common.last_scanned_qr_type))
# print('common.last_scanned_ur_prefix={}'.format(common.last_scanned_ur_prefix))
break
progress = '{} OF {}'.format(qr_decoder.received_parts(), qr_decoder.total_parts())

4
ports/stm32/boards/Passport/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h

@ -625,12 +625,12 @@ STATIC mp_obj_t mod_trezorcrypto_bip32_deserialize(mp_obj_t value, mp_obj_t vers
HDNode hdnode;
uint32_t fingerprint;
if (_is_public) {
printf("Calling hdnode_deserialize_public()\n");
// printf("Calling hdnode_deserialize_public()\n");
if (hdnode_deserialize_public(valueb.buf, _version, SECP256K1_NAME, &hdnode, &fingerprint) < 0) {
mp_raise_ValueError("Failed to deserialize public");
}
} else {
printf("Calling hdnode_deserialize_private()\n");
// printf("Calling hdnode_deserialize_private()\n");
if (hdnode_deserialize_private(valueb.buf, _version, SECP256K1_NAME, &hdnode, &fingerprint) < 0) {
mp_raise_ValueError("Failed to deserialize private");
}

Loading…
Cancel
Save