Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc511ee34c | ||
|
|
41b9a98f6a | ||
|
|
506345003a | ||
|
|
e7f325a176 | ||
|
|
d53dc15fa4 | ||
|
|
0c0e9f0029 | ||
|
|
94b9831590 | ||
|
|
7545e8029b | ||
|
|
a3fc1a7261 | ||
|
|
c203669206 | ||
|
|
576c29a1c7 | ||
|
|
c272bc434e | ||
|
|
c34a2e4470 | ||
|
|
f1d4bbd390 | ||
|
|
13d2d8cc10 | ||
|
|
c59dc3539f | ||
|
|
56c2077174 | ||
|
|
3ad740fdfe | ||
|
|
26feb449e5 | ||
|
|
21fbd1afcd | ||
|
|
c2b5c0d97d | ||
|
|
a19d16d814 | ||
|
|
8bb799b408 | ||
|
|
3364108f40 | ||
|
|
ae22952660 | ||
|
|
6c3018de20 | ||
|
|
cb7b5c904c | ||
|
|
dc685541cc | ||
|
|
b6ba85c9f4 | ||
|
|
53cfb999f7 | ||
|
|
92cc8e51a1 | ||
|
|
2750abfbeb | ||
|
|
63f7647c21 | ||
|
|
27045d90f6 | ||
|
|
ec3a32c241 | ||
|
|
09d64a7263 | ||
|
|
1cbe864472 | ||
|
|
0237bb23da | ||
|
|
968ba55e16 | ||
|
|
affe18cee8 | ||
|
|
8aacf472e2 | ||
|
|
a273eb7603 | ||
|
|
87522a0d99 | ||
|
|
ff442790ac | ||
|
|
1c40afbef1 | ||
|
|
a3e90157c3 | ||
|
|
e6e6cd26b9 | ||
|
|
2d5228a5cf | ||
|
|
d3dddc4483 | ||
|
|
5ff396a808 | ||
|
|
6a1509f845 | ||
|
|
ea538cc45a | ||
|
|
2724b0e55f | ||
|
|
069526d693 | ||
|
|
e09c058bca |
@ -288,6 +288,12 @@ def doit(keydir, outfn=None, build_dir='l-port/build-COLDCARD', high_water=False
|
||||
hw_compat = CURRENT_HARDWARE
|
||||
|
||||
body_len = align_to(len(body), 512)
|
||||
|
||||
if hw_compat & (MK_1_OK | MK_2_OK | MK_3_OK):
|
||||
# bugfix: size must be non-page aligned, so extra bytes are erased past end
|
||||
if (body_len % 4096) == 0:
|
||||
body_len += 512
|
||||
|
||||
assert body_len % 512 == 0, body_len
|
||||
|
||||
# pad out
|
||||
|
||||
2
external/ckcc-protocol
vendored
2
external/ckcc-protocol
vendored
@ -1 +1 @@
|
||||
Subproject commit 9abbe10db4c8f16f9731d422dcd5635c1d10b230
|
||||
Subproject commit f3033b9dce8619c3ad89bdd840f5c91156d9598c
|
||||
2
external/libngu
vendored
2
external/libngu
vendored
@ -1 +1 @@
|
||||
Subproject commit 0b9d7600d12d0eda6877f8188b098088c2261912
|
||||
Subproject commit 356b9137cf7ddf5de66ec4cdc0a4d757b2e42790
|
||||
2
external/micropython
vendored
2
external/micropython
vendored
@ -1 +1 @@
|
||||
Subproject commit c087bbe8d273a940482bdb00c806f430960d6d9c
|
||||
Subproject commit f3b2a8c2e988fc9cdf16812bb48a9964911329a9
|
||||
@ -1,4 +1,33 @@
|
||||
## 4.1.4 - Nov ??, 2021
|
||||
## 4.1.9 - Jun 26, 2023
|
||||
|
||||
- Bugfix: QR codes could not be rendered in 4.1.8 release due to a regression.
|
||||
|
||||
## 4.1.8 - Jun 19, 2023
|
||||
|
||||
- Bugfix: "Validating..." screen would be shown twice in some cases. Improves signing performance.
|
||||
- Bugfix: Reproducible builds corrected.
|
||||
|
||||
## 4.1.7 - Nov 15, 2022
|
||||
|
||||
- Bugfix: Upgrades to 4.1.6 version using SD Card did not work due to an obscure alignment
|
||||
bug. USB upgrade did work. A workaround to this issue has been added for this release.
|
||||
|
||||
## 4.1.6 - Oct 5, 2022
|
||||
|
||||
- Bugfix: order of multisig wallet registration does NOT matter in PSBT signing
|
||||
- Bugfix: allow unknown scripts in HSM mode
|
||||
- Enhancement: `OP_RETURN` is now a known script and is displayed in ascii if possible
|
||||
|
||||
## 4.1.5 - May 4, 2022
|
||||
|
||||
- Enhancement: Support P2TR outputs (pay to Taproot) in PSBT files. Allows
|
||||
on-screen verification of P2TR destination addresses (`bc1p..`) so you can send
|
||||
your BTC to them. Does **not** support signing, so you cannot operate a Taproot
|
||||
wallet with Mk3 COLDCARD as the signing device.
|
||||
- Bugfix: Yikes error shown during BIP-85 menu operation.
|
||||
- Enhancement: Rename "Derive Entropy" to "Derive Seed B85" to match Mk4 menus
|
||||
|
||||
## 4.1.4 - Apr 26, 2022
|
||||
|
||||
- Enhancement: if an XFP of zero is seen in a PSBT file, assume that should be replaced by
|
||||
our current XFP value and try to sign the input (same for change outputs and change-fraud
|
||||
@ -8,6 +37,8 @@
|
||||
BIP-84 / BIP-44 / BIP-49 standard derivations, as a QR. Also can show XFP and master XPUB.
|
||||
- Bugfix: Updated domain name from `coldcardwallet.com` to `coldcard.com` in docs and few
|
||||
on-screen messages.
|
||||
- Bugfix: allow sending to scripts that we cannot parse, with a warning, to support
|
||||
`OP_RETURN` and other outputs we don't understand well (yet).
|
||||
|
||||
## 4.1.3 - Sep 2, 2021
|
||||
|
||||
|
||||
@ -1,26 +1,28 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA256
|
||||
|
||||
715a3ec7a91d2366788b14a243e7343de875714b647d1e2bc906ecc5b752d8d9 README.md
|
||||
264ab07ec957520d1c8ae46a4b0a398c62b1e63cf8d20f56c9092890560fc592 README.md
|
||||
a0c4d0ac3881a36704f0b620a13c72704531f656ee29368d5aac87dc5f21c7a1 History.md
|
||||
90dc85f0bedbda32270af1aed97ac7356fe15dc4eeb95db11af4bb037c000018 ChangeLog.md
|
||||
8f71336a78573ccbd19b782e4f6e5930a8f944517884fe02d26eb0f38bf5c3ac ChangeLog.md
|
||||
f6fb19d95bd1e38535f137bed60cafbfcd52379a686e3d12f372f881d78e640e 2023-06-26T1241-v4.1.9-coldcard.dfu
|
||||
233398cc8f6b9e894072448eb8b8a82a4f546219ce461dd821f0ed0a38b61900 2023-06-19T1627-v4.1.8-coldcard.dfu
|
||||
cc946bcb63211e15d85db577e25ab2432d4a74d5dad77d710539e505dce7914a 2022-11-14T1854-v4.1.7-coldcard.dfu
|
||||
bc4d0b2b985aea3a78eb9351cdadf60d1ab00801ed1e7192765b94181cb8933b 2022-10-05T1517-v4.1.6-coldcard.dfu
|
||||
5aa2ccc65e2e5279db78b3068b9f3c60c34dd7cc330c2cc1243160db31a2d0f0 2022-05-04T1258-v4.1.5-coldcard.dfu
|
||||
9bb028d3e60239f0fcdb3b1f91075785e2c21795789b38c4c619c1f64c2950ef 2022-04-25T1618-v4.1.4-coldcard.dfu
|
||||
dedfcf8385e35dbdbb26b92f8c0667105404062ad83c8830d809cf9193434d9c 2021-09-02T1752-v4.1.3-coldcard.dfu
|
||||
d01d81305b209dadcf960b9e9d20affb8d4f11e9f9f916c5a06be29298c80dc2 2021-07-28T1347-v4.1.2-coldcard.dfu
|
||||
08e1ec1fd073afbbc9014db6da07fd96c6b20a6710fe491eb805afeba865fe3f 2021-04-30T1748-v4.1.1-coldcard.dfu
|
||||
2c39330bef467af8dcd7e2f393a970e1ca177b1812f830269916657ff79598eb 2021-04-29T1725-v4.1.0-coldcard.dfu
|
||||
5e0c5f4ba9fa0e5fd7f9846e25c6cd28821a86ff5e1207c56cc3a4f4c3741f15 2021-04-07T1424-v4.0.2-coldcard.dfu
|
||||
f05bc8dfed047c0c0abe5ed60621d2d14899b10717221c4af0942d96a1754f33 2021-03-29T1927-v4.0.1-coldcard.dfu
|
||||
3097fa3c173247637aa27376036e384940adeb67ce727c9795471f46deaa5210 2021-01-14T1617-v3.2.2-coldcard.dfu
|
||||
9e4aeee48d4399a761fec5d4c65cb2495ef5bc0b46995c085d63a65cf67362cb 2021-01-07T1439-v3.2.1-coldcard.dfu
|
||||
bea27f263b524a66b3ed0a58c16805e98be0d7c3db20c2f7aab3238f2c6a6995 2019-12-19T1623-v3.0.6-coldcard.dfu
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQEzBAEBCAAdFiEERYl3mt/BTzMnU06oo6MbrVoqWxAFAmExD3kACgkQo6MbrVoq
|
||||
WxDE5gf/Sm8Rf278CyD2z1P6nQgqgYK3sIOL+aF68JpjQ8WXzCGA/KIHSVCC8GSt
|
||||
aIJyR0O2F9wiHpAC9f1KHQySqC9VuJ/3z+H8LnLJ7j218O4Y3ojylXw7q61c7FD9
|
||||
327emLD6OuX8L4l6JDlunqb+BJGsTwtpVpdQhWdZjrdYMDxvMdqWqoBuzIgegHJr
|
||||
1tstoM9py7ygzyqXTF2bXMYGiWmZC/Ak7J0TbZYU9dixAF+m/OPQC9nvKYRRiKFM
|
||||
Mcc3ylIdWYEC3sygUodtcItrdSYKBMQ47ubMBewk/Dp8fJwvnIV/cH4pZ5s/2pV7
|
||||
c59R52ZY0vC68Ql0cr5h6+AmikbdNA==
|
||||
=9L7S
|
||||
iQEzBAEBCAAdFiEERYl3mt/BTzMnU06oo6MbrVoqWxAFAmSZh3UACgkQo6MbrVoq
|
||||
WxCDAgf+Ichyvxaz/LW4CdaMEI9OPUmPaz1NeaSQVuEP1Px8V92iUqbwHoymsH7T
|
||||
jelo0ylCpW4QLxUE5lo3GCdAJrnzv6oHQHNTABIO3+iFUL239DZsP2jSHkf+mXNU
|
||||
CAf9iutfR1Zfkze9y3H8caKbDEFBLdSnJaPE9wegeeN4lfU6/I0UGs8NvTzdU6ui
|
||||
O/hJDZhWm8LL1ygsgmHw3hM7W+0MNDsdL737ZlGLRRc3cPNzIxTIPTeNm1+EVFJj
|
||||
6PgmBGP7ffIqN7Sui6sF/EQ5YihlqaY4yrzXBiVlNbpShXBBmwXUgleCmKkpfDsC
|
||||
8uhe7fHEjLSQMUviByn6YtOZ9VqW3Q==
|
||||
=paER
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
@ -377,9 +377,28 @@ class ApproveTransaction(UserAuthorizedAction):
|
||||
# - gives user-visible string
|
||||
#
|
||||
val = ' '.join(self.chain.render_value(o.nValue))
|
||||
dest = self.chain.render_address(o.scriptPubKey)
|
||||
try:
|
||||
dest = self.chain.render_address(o.scriptPubKey)
|
||||
|
||||
return '%s\n - to address -\n%s\n' % (val, dest)
|
||||
return '%s\n - to address -\n%s\n' % (val, dest)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# check for OP_RETURN
|
||||
data = self.chain.op_return(o.scriptPubKey)
|
||||
if data:
|
||||
data_hex, data_ascii = data
|
||||
to_ret = '%s\n - OP_RETURN -\n%s' % (val, data_hex)
|
||||
if data_ascii:
|
||||
return to_ret + " (ascii: %s)\n" % data_ascii
|
||||
return to_ret + "\n"
|
||||
|
||||
# Handle future things better: allow them to happen at least.
|
||||
self.psbt.warnings.append(
|
||||
('Output?', 'Sending to a script that is not well understood.'))
|
||||
dest = B2A(o.scriptPubKey)
|
||||
|
||||
return '%s\n - to script -\n%s\n' % (val, dest)
|
||||
|
||||
|
||||
async def interact(self):
|
||||
@ -695,11 +714,10 @@ def sign_psbt_file(filename):
|
||||
# sign a PSBT file found on a MicroSD card
|
||||
from files import CardSlot, CardMissingError, securely_blank_file
|
||||
from glob import dis
|
||||
from ux import the_ux
|
||||
from sram2 import tmp_buf
|
||||
from utils import HexStreamer, Base64Streamer, HexWriter, Base64Writer
|
||||
|
||||
UserAuthorizedAction.cleanup()
|
||||
|
||||
#print("sign: %s" % filename)
|
||||
|
||||
|
||||
@ -862,10 +880,9 @@ def sign_psbt_file(filename):
|
||||
|
||||
UserAuthorizedAction.cleanup()
|
||||
|
||||
UserAuthorizedAction.cleanup()
|
||||
UserAuthorizedAction.active_request = ApproveTransaction(psbt_len, approved_cb=done)
|
||||
|
||||
# kill any menu stack, and put our thing at the top
|
||||
abort_and_goto(UserAuthorizedAction.active_request)
|
||||
the_ux.push(UserAuthorizedAction.active_request)
|
||||
|
||||
class RemoteBackup(UserAuthorizedAction):
|
||||
def __init__(self):
|
||||
|
||||
@ -4,11 +4,12 @@
|
||||
#
|
||||
import ngu
|
||||
from uhashlib import sha256
|
||||
from ubinascii import hexlify as b2a_hex
|
||||
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 serializations import hash160, ser_compact_size
|
||||
from serializations import hash160, ser_compact_size, disassemble
|
||||
from ucollections import namedtuple
|
||||
from opcodes import OP_CHECKMULTISIG
|
||||
from opcodes import OP_CHECKMULTISIG, OP_RETURN
|
||||
|
||||
# See SLIP 132 <https://github.com/satoshilabs/slips/blob/master/slip-0132.md>
|
||||
# for background on these version bytes. Not to be confused with SLIP-32 which involves Bech32.
|
||||
@ -201,12 +202,29 @@ class ChainsBase:
|
||||
if ll == 22 and script[0:2] == b'\x00\x14':
|
||||
return ngu.codecs.segwit_encode(cls.bech32_hrp, 0, script[2:])
|
||||
|
||||
# P2WSH
|
||||
if ll == 34 and script[0:2] == b'\x00\x20':
|
||||
return ngu.codecs.segwit_encode(cls.bech32_hrp, 0, script[2:])
|
||||
# P2WSH, P2TR and later
|
||||
if ll == 34 and script[0] <= 16 and script[1] == 0x20:
|
||||
return ngu.codecs.segwit_encode(cls.bech32_hrp, script[0], script[2:])
|
||||
|
||||
raise ValueError('Unknown payment script', repr(script))
|
||||
|
||||
@classmethod
|
||||
def op_return(cls, script):
|
||||
"""Returns decoded string op return data if script is op return otherwise None"""
|
||||
gen = disassemble(script)
|
||||
script_type = next(gen)
|
||||
if OP_RETURN in script_type:
|
||||
data = next(gen)[0]
|
||||
data_hex = b2a_hex(data).decode()
|
||||
data_ascii = None
|
||||
if min(data) >= 32 and max(data) < 127: # printable
|
||||
try:
|
||||
data_ascii = data.decode("ascii")
|
||||
except:
|
||||
pass
|
||||
return data_hex, data_ascii
|
||||
return None
|
||||
|
||||
class BitcoinMain(ChainsBase):
|
||||
# see <https://github.com/bitcoin/bitcoin/blob/master/src/chainparams.cpp#L140>
|
||||
ctype = 'BTC'
|
||||
|
||||
@ -43,7 +43,8 @@ still backed-up.''')
|
||||
|
||||
def drv_entro_step2(_1, picked, _2):
|
||||
from glob import dis
|
||||
from files import CardSlot, CardMissingError, needs_microsd
|
||||
from files import CardSlot, CardMissingError
|
||||
from actions import needs_microsd
|
||||
|
||||
the_ux.pop()
|
||||
|
||||
|
||||
@ -197,7 +197,7 @@ AdvancedNormalMenu = [
|
||||
MenuItem("MicroSD Card", menu=SDCardMenu),
|
||||
MenuItem('Paper Wallets', f=make_paper_wallet, predicate=lambda: make_paper_wallet),
|
||||
MenuItem('User Management', menu=make_users_menu, predicate=lambda: version.has_fatram),
|
||||
MenuItem('Derive Entropy', f=drv_entro_start),
|
||||
MenuItem('Derive Seed B85', f=drv_entro_start),
|
||||
MenuItem("Export XPUB", menu=XpubExportMenu),
|
||||
MenuItem("Danger Zone", menu=DangerZoneMenu),
|
||||
]
|
||||
|
||||
@ -759,7 +759,10 @@ class HSMPolicy:
|
||||
for idx, tx_out in psbt.output_iter():
|
||||
if not psbt.outputs[idx].is_change:
|
||||
total_out += tx_out.nValue
|
||||
dests.append(chain.render_address(tx_out.scriptPubKey))
|
||||
try:
|
||||
dests.append(chain.render_address(tx_out.scriptPubKey))
|
||||
except ValueError:
|
||||
dests.append(str(b2a_hex(tx_out.scriptPubKey), 'ascii'))
|
||||
|
||||
# Pick a rule to apply to this specific txn
|
||||
reasons = []
|
||||
|
||||
@ -278,6 +278,9 @@ class MultisigWallet:
|
||||
# the same prefix path per-each xfp, as indicated
|
||||
# xfp_paths (unordered)?
|
||||
# - could also check non-prefix part is all non-hardened
|
||||
if len(xfp_paths) != len(self.xfp_paths):
|
||||
# cannot be the same if len(w0.N) != len(w1.N)
|
||||
return False
|
||||
for x in xfp_paths:
|
||||
if x[0] not in self.xfp_paths:
|
||||
return False
|
||||
|
||||
@ -32,7 +32,7 @@ OP_16 = const(96)
|
||||
#OP_ELSE = const(103)
|
||||
#OP_ENDIF = const(104)
|
||||
#OP_VERIFY = const(105)
|
||||
#OP_RETURN = const(106)
|
||||
OP_RETURN = const(106)
|
||||
#OP_TOALTSTACK = const(107)
|
||||
#OP_FROMALTSTACK = const(108)
|
||||
#OP_2DROP = const(109)
|
||||
|
||||
@ -1071,8 +1071,7 @@ class psbtObject(psbtProxy):
|
||||
assert N == len(xfp_paths)
|
||||
|
||||
for c in candidates:
|
||||
if c.M == M:
|
||||
assert c.N == N
|
||||
if c.M == M and c.N == N:
|
||||
self.active_multisig = c
|
||||
break
|
||||
|
||||
|
||||
@ -112,6 +112,9 @@ class USBHandler:
|
||||
|
||||
self.encrypted_req = False
|
||||
|
||||
# not bound to a specific crypto setup by default
|
||||
self.bound = False
|
||||
|
||||
# these will be objects later
|
||||
self.encrypt = None
|
||||
self.decrypt = None
|
||||
@ -169,6 +172,9 @@ class USBHandler:
|
||||
if not(4 <= msg_len <= MAX_MSG_LEN):
|
||||
raise FramingError('badsz')
|
||||
|
||||
if not is_encrypted and self.bound:
|
||||
raise FramingError('must encrypt')
|
||||
|
||||
if is_encrypted:
|
||||
if self.decrypt is None:
|
||||
raise FramingError('no key')
|
||||
@ -596,6 +602,11 @@ class USBHandler:
|
||||
|
||||
#print("USB garbage: %s +[%d]" % (cmd, len(args)))
|
||||
|
||||
# Force logout if bound and unknown command received
|
||||
if self.bound:
|
||||
from utils import clean_shutdown, call_later_ms
|
||||
call_later_ms(250, clean_shutdown)
|
||||
|
||||
return b'err_Unknown cmd'
|
||||
|
||||
|
||||
@ -606,9 +617,15 @@ class USBHandler:
|
||||
def handle_crypto_setup(self, version, his_pubkey):
|
||||
# pick a one-time key pair for myself, and return the pubkey for that
|
||||
# determine what the session key will be for this connection
|
||||
assert version == 0x1
|
||||
if version not in [0x1, 0x2]:
|
||||
raise FramingError('bad ncry version')
|
||||
assert len(his_pubkey) == 64
|
||||
|
||||
if self.bound:
|
||||
raise FramingError('crypto already set up')
|
||||
if version == 0x2:
|
||||
self.bound = True
|
||||
|
||||
# pick a random key pair, just for this session
|
||||
pair = ngu.secp256k1.keypair()
|
||||
my_pubkey = pair.pubkey().to_bytes(True) # un-compressed
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
//
|
||||
// AUTO-generated.
|
||||
//
|
||||
// built: 2021-09-02
|
||||
// version: 4.1.3
|
||||
// built: 2023-06-26
|
||||
// version: 4.1.9
|
||||
//
|
||||
#include <stdint.h>
|
||||
|
||||
// this overrides ports/stm32/fatfs_port.c
|
||||
uint32_t get_fattime(void) {
|
||||
return 0x53222020UL;
|
||||
return 0x56da2020UL;
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ BOOTLOADER_BASE = 0x08000000
|
||||
FILESYSTEM_BASE = 0x080e0000
|
||||
|
||||
# Our version for this release.
|
||||
VERSION_STRING = 4.1.3
|
||||
VERSION_STRING = 4.1.9
|
||||
|
||||
#
|
||||
# Sign and merge various parts
|
||||
@ -266,7 +266,7 @@ ifeq ($(PUBLISHED_BIN),)
|
||||
@echo "Need published binary for: $(VERSION_STRING)"
|
||||
@echo ""
|
||||
@echo "Code in repro-build.sh should have placed it there already!?"
|
||||
false
|
||||
@echo ""
|
||||
else
|
||||
@echo Comparing against: $(PUBLISHED_BIN)
|
||||
test -n "$(PUBLISHED_BIN)" -a -f $(PUBLISHED_BIN)
|
||||
|
||||
@ -6,13 +6,7 @@
|
||||
# <https://blog.feabhas.com/2017/12/introduction-docker-embedded-developers-part-4-reducing-docker-image-size/>
|
||||
#
|
||||
|
||||
# PROBLEM: alpine has `gcc-arm-none-eabi` but it's not in main repo, instead its part of "edge"?
|
||||
#
|
||||
# - for firmware v4.0.2, I used alphine:3.13.2 as base, but that doesn't work now for
|
||||
# some random reason, and I don't care to debug why.
|
||||
#
|
||||
#FROM alpine:3.13.2
|
||||
FROM alpine:edge
|
||||
FROM alpine:3.16.0
|
||||
|
||||
WORKDIR /work
|
||||
|
||||
|
||||
@ -36,17 +36,24 @@ cd ../stm32
|
||||
cd ../releases
|
||||
if [ -f *-v$VERSION_STRING-coldcard.dfu ]; then
|
||||
echo "Using existing binary in ../releases, not downloading."
|
||||
PUBLISHED_BIN=`realpath *-v$VERSION_STRING-coldcard.dfu`
|
||||
else
|
||||
# fetch a copy of the required binary
|
||||
PUBLISHED_BIN=`grep $VERSION_STRING signatures.txt | dd bs=66 skip=1`
|
||||
PUBLISHED_BIN=`grep -F $VERSION_STRING signatures.txt | dd bs=66 skip=1`
|
||||
if [ -z "$PUBLISHED_BIN" ]; then
|
||||
echo "Cannot determine release date / full file name. Stop."
|
||||
exit 1
|
||||
echo "No existing signature for this binary version. Nothing to check against."
|
||||
else
|
||||
wget -S https://coldcard.com/downloads/$PUBLISHED_BIN
|
||||
PUBLISHED_BIN=`realpath "$PUBLISHED_BIN"`
|
||||
fi
|
||||
wget -S https://coldcard.com/downloads/$PUBLISHED_BIN
|
||||
fi
|
||||
cd ../stm32
|
||||
|
||||
if [ -z "$SOURCE_DATE_EPOCH" ] && [ -n "$PUBLISHED_BIN" ]; then
|
||||
DT=$(basename $PUBLISHED_BIN | cut -d "-" -f1,2,3)
|
||||
export SOURCE_DATE_EPOCH=$(python -c 'import datetime, sys; sys.stdout.write(str(int(datetime.datetime.strptime(sys.argv[1], "%Y-%m-%dT%H%M").timestamp())))' "$DT")
|
||||
fi
|
||||
|
||||
make setup
|
||||
make all
|
||||
make $TARGETS
|
||||
@ -57,7 +64,7 @@ if [ $PWD != '/work/src/stm32' ]; then
|
||||
fi
|
||||
|
||||
set +e
|
||||
make check-repro
|
||||
make "PUBLISHED_BIN=$PUBLISHED_BIN" check-repro
|
||||
|
||||
set +ex
|
||||
if [ $PWD != '/work/src/stm32' ]; then
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# (c) Copyright 2020 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
||||
#
|
||||
# Access a local bitcoin-Qt/bitcoind on testnet
|
||||
# Access a local bitcoin-Qt/bitcoind on testnet (must be v22 or higher)
|
||||
#
|
||||
# Must have these lines in the bitcoin.conf file:
|
||||
#
|
||||
@ -11,7 +11,7 @@ import pytest, os
|
||||
from bitcoinrpc.authproxy import AuthServiceProxy
|
||||
from base64 import b64encode, b64decode
|
||||
|
||||
URL = '127.0.0.1:18332'
|
||||
URL = '127.0.0.1:18332/wallet/'
|
||||
|
||||
def get_cookie():
|
||||
# read local bitcoind cookie .. highly mac-only
|
||||
@ -34,6 +34,7 @@ def bitcoind():
|
||||
conn = AuthServiceProxy('http://' + cookie + '@' + URL)
|
||||
|
||||
assert conn.getblockchaininfo()['chain'] == 'test'
|
||||
assert conn.getnetworkinfo()['version'] >= 220000, "we require >= 22.0 of Core"
|
||||
|
||||
return conn
|
||||
|
||||
|
||||
@ -819,7 +819,7 @@ def check_against_bitcoind(bitcoind, sim_exec, sim_execfile):
|
||||
if dests:
|
||||
# check we got right destination address(es)
|
||||
for outn, expect_addr in dests:
|
||||
assert decode['vout'][outn]['scriptPubKey']['addresses'][0] == expect_addr
|
||||
assert decode['vout'][outn]['scriptPubKey']['address'] == expect_addr
|
||||
|
||||
# leverage bitcoind's transaction decoding
|
||||
ex = dict( lock_time = decode['locktime'],
|
||||
@ -829,7 +829,7 @@ def check_against_bitcoind(bitcoind, sim_exec, sim_execfile):
|
||||
miner_fee = U2SAT(fee),
|
||||
warnings_expected = num_warn,
|
||||
total_value_out = sum(U2SAT(i['value']) for i in decode['vout']),
|
||||
destinations = [(U2SAT(i['value']), i['scriptPubKey']['addresses'][0])
|
||||
destinations = [(U2SAT(i['value']), i['scriptPubKey']['address'])
|
||||
for i in decode['vout']],
|
||||
)
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ def test_bip_vectors(mode, index, entropy, expect,
|
||||
|
||||
goto_home()
|
||||
pick_menu_item('Advanced')
|
||||
pick_menu_item('Derive Entropy')
|
||||
pick_menu_item('Derive Seed B85')
|
||||
|
||||
time.sleep(0.1)
|
||||
title, story = cap_story()
|
||||
@ -196,7 +196,7 @@ def test_path_index(mode, pattern, index,
|
||||
|
||||
goto_home()
|
||||
pick_menu_item('Advanced')
|
||||
pick_menu_item('Derive Entropy')
|
||||
pick_menu_item('Derive Seed B85')
|
||||
|
||||
time.sleep(0.1)
|
||||
title, story = cap_story()
|
||||
|
||||
@ -208,7 +208,7 @@ def test_io_size(request, decode_with_bitcoind, fake_txn, is_mark3,
|
||||
shown = set()
|
||||
hidden = set()
|
||||
for i in decoded['vout']:
|
||||
dest = i['scriptPubKey']['addresses'][0]
|
||||
dest = i['scriptPubKey']['address']
|
||||
val = i['value']
|
||||
if dest in story:
|
||||
shown.add((val, dest))
|
||||
@ -1292,18 +1292,18 @@ def test_wrong_xfp_multi(fake_txn, try_sign, segwit):
|
||||
# - but multiple wrong XFP values
|
||||
|
||||
wrongs = set()
|
||||
wrong_xfp = b'\x12\x34\x56\x78'
|
||||
|
||||
def hack(psbt):
|
||||
# change all inputs to be "not ours" ... but with utxo details
|
||||
for idx, i in enumerate(psbt.inputs):
|
||||
for pubkey in i.bip32_paths:
|
||||
here = struct.pack('<I', idx)
|
||||
here = struct.pack('<I', idx+73)
|
||||
i.bip32_paths[pubkey] = here + i.bip32_paths[pubkey][4:]
|
||||
wrongs.add(xfp2str(idx))
|
||||
wrongs.add(xfp2str(idx+73))
|
||||
|
||||
psbt = fake_txn(7, 2, segwit_in=segwit, psbt_hacker=hack)
|
||||
|
||||
open('debug/wrong-xfp.psbt', 'wb').write(psbt)
|
||||
with pytest.raises(CCProtoError) as ee:
|
||||
orig, result = try_sign(psbt, accept=True)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user