@@ -62,7 +62,7 @@ class btchip:
6262 BTCHIP_INS_EXT_CACHE_GET_FEATURES = 0x26
6363
6464 OPERATION_MODE_WALLET = 0x01
65- OPERATION_MODE_RELAXED_WALLET = 0x02
65+ OPERATION_MODE_RELAXED_WALLET = 0x02
6666 OPERATION_MODE_SERVER = 0x04
6767 OPERATION_MODE_DEVELOPER = 0x08
6868
@@ -159,6 +159,7 @@ def getTrustedInput(self, transaction, index):
159159 apdu .extend (params )
160160 self .dongle .exchange (bytearray (apdu ))
161161 # Each output
162+ indexOutput = 0
162163 for troutput in transaction .outputs :
163164 apdu = [ self .BTCHIP_CLA , self .BTCHIP_INS_GET_TRUSTED_INPUT , 0x80 , 0x00 ]
164165 params = bytearray (troutput .amount )
@@ -187,7 +188,20 @@ def getTrustedInput(self, transaction, index):
187188
188189 def startUntrustedTransaction (self , newTransaction , inputIndex , outputList , redeemScript ):
189190 # Start building a fake transaction with the passed inputs
190- apdu = [ self .BTCHIP_CLA , self .BTCHIP_INS_HASH_INPUT_START , 0x00 , (0x00 if newTransaction else 0x80 ) ]
191+ segwit = False
192+ if newTransaction :
193+ for passedOutput in outputList :
194+ if ('witness' in passedOutput ) and passedOutput ['witness' ]:
195+ segwit = True
196+ break
197+ if newTransaction :
198+ if segwit :
199+ p2 = 0x02
200+ else :
201+ p2 = 0x00
202+ else :
203+ p2 = 0x80
204+ apdu = [ self .BTCHIP_CLA , self .BTCHIP_INS_HASH_INPUT_START , 0x00 , p2 ]
191205 params = bytearray ([0x01 , 0x00 , 0x00 , 0x00 ]) # default version
192206 writeVarint (len (outputList ), params )
193207 apdu .append (len (params ))
@@ -199,11 +213,13 @@ def startUntrustedTransaction(self, newTransaction, inputIndex, outputList, rede
199213 apdu = [ self .BTCHIP_CLA , self .BTCHIP_INS_HASH_INPUT_START , 0x80 , 0x00 ]
200214 params = []
201215 script = redeemScript
202- if passedOutput ['trustedInput' ]:
216+ if ('witness' in passedOutput ) and passedOutput ['witness' ]:
217+ params .append (0x02 )
218+ elif ('trustedInput' in passedOutput ) and passedOutput ['trustedInput' ]:
203219 params .append (0x01 )
204220 else :
205221 params .append (0x00 )
206- if passedOutput ['trustedInput' ]:
222+ if ( 'trustedInput' in passedOutput ) and passedOutput ['trustedInput' ]:
207223 params .append (len (passedOutput ['value' ]))
208224 params .extend (passedOutput ['value' ])
209225 if currentIndex <> inputIndex :
@@ -236,6 +252,7 @@ def finalizeInput(self, outputAddress, amount, fees, changePath, rawTx=None):
236252 if self .needKeyCache :
237253 self .resolvePublicKeysInPath (changePath )
238254 result = {}
255+ outputs = None
239256 if rawTx is not None :
240257 try :
241258 fullTx = bitcoinTransaction (bytearray (rawTx ))
@@ -278,7 +295,14 @@ def finalizeInput(self, outputAddress, amount, fees, changePath, rawTx=None):
278295 result ['keycardData' ] = response [offset : offset + keycardDataLength ]
279296 offset = offset + keycardDataLength
280297 result ['secureScreenData' ] = response [offset :]
281- result ['outputData' ] = response [1 : 1 + response [0 ]]
298+ if result ['confirmationType' ] == 0x04 :
299+ offset = 1 + response [0 ] + 1
300+ keycardDataLength = response [offset ]
301+ result ['keycardData' ] = response [offset + 1 : offset + 1 + keycardDataLength ]
302+ if outputs == None :
303+ result ['outputData' ] = response [1 : 1 + response [0 ]]
304+ else :
305+ result ['outputData' ] = outputs
282306 return result
283307
284308 def finalizeInputFull (self , outputData ):
@@ -299,20 +323,22 @@ def finalizeInputFull(self, outputData):
299323 response = self .dongle .exchange (bytearray (apdu ))
300324 encryptedOutputData = encryptedOutputData + response [1 : 1 + response [0 ]]
301325 offset += dataLength
302- result ['confirmationNeeded' ] = response [1 + response [0 ]] <> 0x00
303- result ['confirmationType' ] = response [1 + response [0 ]]
304- if result ['confirmationType' ] == 0x02 :
326+ result ['confirmationNeeded' ] = response [1 + response [0 ]] <> 0x00
327+ result ['confirmationType' ] = response [1 + response [0 ]]
328+ if result ['confirmationType' ] == 0x02 :
329+ result ['keycardData' ] = response [1 + response [0 ] + 1 :] # legacy
330+ if result ['confirmationType' ] == 0x03 :
305331 offset = 1 + response [0 ] + 1
306332 keycardDataLength = response [offset ]
307- result [ 'keycardData' ] = response [ offset : offset + keycardDataLength ]
308- if result ['confirmationType ' ] == 0x03 :
309- offset = 1 + response [ 0 ] + 1
310- keycardDataLength = response [offset ]
311- offset = offset + 1
312- result ['keycardData ' ] = response [ offset : offset + keycardDataLength ]
313- offset = offset + keycardDataLength
314- result [ 'secureScreenData' ] = response [offset : ]
315- result [ 'encryptedOutputData' ] = encryptedOutputData
333+ offset = offset + 1
334+ result ['keycardData ' ] = response [ offset : offset + keycardDataLength ]
335+ offset = offset + keycardDataLength
336+ result [ 'secureScreenData' ] = response [offset : ]
337+ result [ 'encryptedOutputData' ] = encryptedOutputData
338+ if result ['confirmationType ' ] == 0x04 :
339+ offset = 1 + response [ 0 ] + 1
340+ keycardDataLength = response [offset ]
341+ result [ 'keycardData' ] = response [ offset + 1 : offset + 1 + keycardDataLength ]
316342 return result
317343
318344 def untrustedHashSign (self , path , pin = "" , lockTime = 0 , sighashType = 0x01 ):
@@ -435,6 +461,14 @@ def setOperationMode(self, operationMode):
435461 apdu = [ self .BTCHIP_CLA , self .BTCHIP_INS_SET_OPERATION_MODE , 0x00 , 0x00 , 0x01 , operationMode ]
436462 self .dongle .exchange (bytearray (apdu ))
437463
464+ def enableAlternate2fa (self , persistent ):
465+ if persistent :
466+ p1 = 0x02
467+ else :
468+ p1 = 0x01
469+ apdu = [ self .BTCHIP_CLA , self .BTCHIP_INS_SET_OPERATION_MODE , p1 , 0x00 , 0x01 , btchip .OPERATION_MODE_WALLET ]
470+ self .dongle .exchange (bytearray (apdu ))
471+
438472 def getFirmwareVersion (self ):
439473 result = {}
440474 apdu = [ self .BTCHIP_CLA , self .BTCHIP_INS_GET_FIRMWARE_VERSION , 0x00 , 0x00 , 0x00 ]
0 commit comments