Skip to content

Commit 3157386

Browse files
committed
EDGE do not re-sign PSBT
1 parent d49ba0d commit 3157386

File tree

2 files changed

+44
-12
lines changed

2 files changed

+44
-12
lines changed

hwilib/devices/ckcc/client.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,18 @@ def hash_password(self, text_password, v3=False):
333333

334334
return pbkdf2_hmac('sha256' if v3 else 'sha512', text_password, salt, PBKDF2_ITER_COUNT)[:32]
335335

336+
def firmware_version(self):
337+
return self.send_recv(CCProtocolPacker.version()).split("\n")
338+
339+
def is_edge(self):
340+
# returns True if device is running EDGE firmware version
341+
if self.is_simulator:
342+
cmd = "import version; RV.write(str(int(getattr(version, 'is_edge', 0))))"
343+
rv = self.send_recv(b'EXEC' + cmd.encode('utf-8'), timeout=60000, encrypt=False)
344+
return rv == b"1"
345+
346+
return self.firmware_version()[1][-1] == "X"
347+
336348

337349
class UnixSimulatorPipe:
338350
# Use a UNIX pipe to the simulator instead of a real USB connection.

hwilib/devices/coldcard.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,23 @@ def __init__(self, path: str, password: Optional[str] = None, expert: bool = Fal
100100
device.open_path(path.encode())
101101
self.device = ColdcardDevice(dev=device)
102102

103+
self._is_edge = None
104+
105+
@property
106+
def is_edge(self):
107+
"""
108+
Cached property, no need to ask device more than once
109+
:return: bool
110+
"""
111+
if self._is_edge is None:
112+
try:
113+
self._is_edge = self.device.is_edge()
114+
except:
115+
# silent fail, normal firmware is implied
116+
pass
117+
118+
return self._is_edge
119+
103120
@coldcard_exception
104121
def get_pubkey_at_path(self, path: str) -> ExtendedKey:
105122
self.device.check_mitm()
@@ -132,14 +149,15 @@ def sign_tx(self, tx: PSBT) -> PSBT:
132149

133150
# For multisigs, we may need to do multiple passes if we appear in an input multiple times
134151
passes = 1
135-
for psbt_in in tx.inputs:
136-
our_keys = 0
137-
for key in psbt_in.hd_keypaths.keys():
138-
keypath = psbt_in.hd_keypaths[key]
139-
if keypath.fingerprint == master_fp and key not in psbt_in.partial_sigs:
140-
our_keys += 1
141-
if our_keys > passes:
142-
passes = our_keys
152+
if not self.is_edge:
153+
for psbt_in in tx.inputs:
154+
our_keys = 0
155+
for key in psbt_in.hd_keypaths.keys():
156+
keypath = psbt_in.hd_keypaths[key]
157+
if keypath.fingerprint == master_fp and key not in psbt_in.partial_sigs:
158+
our_keys += 1
159+
if our_keys > passes:
160+
passes = our_keys
143161

144162
for _ in range(passes):
145163
# Get psbt in hex and then make binary
@@ -392,11 +410,10 @@ def toggle_passphrase(self) -> bool:
392410

393411
def can_sign_taproot(self) -> bool:
394412
"""
395-
The Coldard does not support Taproot yet.
396-
397-
:returns: False, always
413+
Only COLDCARD EDGE support taproot.
414+
:returns: Whether Taproot is supported
398415
"""
399-
return False
416+
return self.is_edge
400417

401418

402419
def enumerate(password: Optional[str] = None, expert: bool = False, chain: Chain = Chain.MAIN, allow_emulators: bool = True) -> List[Dict[str, Any]]:
@@ -422,6 +439,9 @@ def enumerate(password: Optional[str] = None, expert: bool = False, chain: Chain
422439
with handle_errors(common_err_msgs["enumerate"], d_data):
423440
try:
424441
client = ColdcardClient(path)
442+
if client.is_edge:
443+
d_data['label'] = 'edge'
444+
d_data['model'] = 'edge_' + d_data['model']
425445
d_data['fingerprint'] = client.get_master_fingerprint().hex()
426446
except RuntimeError as e:
427447
# Skip the simulator if it's not there

0 commit comments

Comments
 (0)