def getTrustedInput(self, transaction, index): result = {} # Header apdu = [self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x00, 0x00] params = bytearray.fromhex("%.8x" % (index)) params.extend(transaction.version) writeVarint(len(transaction.inputs), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) # Each input for trinput in transaction.inputs: apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00 ] params = bytearray(trinput.prevOut) writeVarint(len(trinput.script), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset = 0 while True: blockLength = 251 if ((offset + blockLength) < len(trinput.script)): dataLength = blockLength else: dataLength = len(trinput.script) - offset params = bytearray(trinput.script[offset:offset + dataLength]) if ((offset + dataLength) == len(trinput.script)): params.extend(trinput.sequence) apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00, len(params) ] apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset += dataLength if (offset >= len(trinput.script)): break # Number of outputs apdu = [self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00] params = [] writeVarint(len(transaction.outputs), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) # Each output indexOutput = 0 for troutput in transaction.outputs: apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00 ] params = bytearray(troutput.amount) writeVarint(len(troutput.script), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset = 0 while (offset < len(troutput.script)): blockLength = 255 if ((offset + blockLength) < len(troutput.script)): dataLength = blockLength else: dataLength = len(troutput.script) - offset apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00, dataLength ] apdu.extend(troutput.script[offset:offset + dataLength]) self.dongle.exchange(bytearray(apdu)) offset += dataLength params = [] if transaction.extra_data: # PACGlobal DIP2 extra data: By appending data to the 'lockTime' transfer we force the device into the # BTCHIP_TRANSACTION_PROCESS_EXTRA mode, which gives us the opportunity to sneak with an additional # data block. if len(transaction.extra_data) > 255 - len(transaction.lockTime): # for now the size should be sufficient raise Exception( 'The size of the DIP2 extra data block has exceeded the limit.' ) writeVarint(len(transaction.extra_data), params) params.extend(transaction.extra_data) apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00, len(transaction.lockTime) + len(params) ] # Locktime apdu.extend(transaction.lockTime) apdu.extend(params) response = self.dongle.exchange(bytearray(apdu)) result['trustedInput'] = True result['value'] = response return result
def getTrustedInput(self, atomic_boolean: AtomicBoolean, ui_tracker: ParsingTracker, transaction, index): result = {} # Header apdu = [ btchip.BTCHIP_CLA, btchip.BTCHIP_INS_GET_TRUSTED_INPUT, 0x00, 0x00 ] params = bytearray.fromhex("%.8x" % index) params.extend(transaction.version) writeVarint(len(transaction.inputs), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) # Each input ui_tracker.set_io_amt(len(transaction.inputs), len(transaction.outputs)) for trinput in transaction.inputs: if atomic_boolean.get_value(): raise UserWarning() apdu = [ btchip.BTCHIP_CLA, btchip.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00 ] params = bytearray(trinput.prevOut) writeVarint(len(trinput.script), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset = 0 while True: blockLength = 251 if ((offset + blockLength) < len(trinput.script)): dataLength = blockLength else: dataLength = len(trinput.script) - offset params = bytearray(trinput.script[offset:offset + dataLength]) if ((offset + dataLength) == len(trinput.script)): params.extend(trinput.sequence) apdu = [ btchip.BTCHIP_CLA, btchip.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00, len(params) ] apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset += dataLength if (offset >= len(trinput.script)): break ui_tracker.tick_in() # Number of outputs apdu = [ btchip.BTCHIP_CLA, btchip.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00 ] params = [] writeVarint(len(transaction.outputs), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) # Each output indexOutput = 0 for troutput in transaction.outputs: if atomic_boolean.get_value(): raise UserWarning() apdu = [ btchip.BTCHIP_CLA, btchip.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00 ] params = bytearray(troutput.amount) writeVarint(len(troutput.script), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset = 0 while (offset < len(troutput.script)): blockLength = 255 if ((offset + blockLength) < len(troutput.script)): dataLength = blockLength else: dataLength = len(troutput.script) - offset apdu = [ btchip.BTCHIP_CLA, btchip.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00, dataLength ] apdu.extend(troutput.script[offset:offset + dataLength]) self.dongle.exchange(bytearray(apdu)) offset += dataLength ui_tracker.tick_out() # Locktime apdu = [ btchip.BTCHIP_CLA, btchip.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00, len(transaction.lockTime) ] apdu.extend(transaction.lockTime) response = self.dongle.exchange(bytearray(apdu)) result['trustedInput'] = True result['value'] = response return result
def startUntrustedTransaction(self, newTransaction, inputIndex, outputList, redeemScript, version: bytearray, cashAddr=False, continueSegwit=False): # Start building a fake transaction with the passed inputs segwit = False if newTransaction: for passedOutput in outputList: if ('witness' in passedOutput) and passedOutput['witness']: segwit = True break if newTransaction: if segwit: p2 = 0x03 if cashAddr else 0x02 else: p2 = 0x00 else: p2 = 0x10 if continueSegwit else 0x80 apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_HASH_INPUT_START, 0x00, p2 ] params = bytearray.fromhex(version) # important to use the combined tx version + tx type field writeVarint(len(outputList), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) # Loop for each input currentIndex = 0 for passedOutput in outputList: if ('sequence' in passedOutput) and passedOutput['sequence']: sequence = bytearray(unhexlify(passedOutput['sequence'])) else: sequence = bytearray([0xFF, 0xFF, 0xFF, 0xFF]) # default sequence apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_HASH_INPUT_START, 0x80, 0x00 ] params = [] script = bytearray(redeemScript) if ('trustedInput' in passedOutput) and passedOutput['trustedInput']: params.append(0x01) elif ('witness' in passedOutput) and passedOutput['witness']: params.append(0x02) else: params.append(0x00) if ('trustedInput' in passedOutput) and passedOutput['trustedInput']: params.append(len(passedOutput['value'])) params.extend(passedOutput['value']) if currentIndex != inputIndex: script = bytearray() writeVarint(len(script), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset = 0 while(offset < len(script)): blockLength = 255 if ((offset + blockLength) < len(script)): dataLength = blockLength else: dataLength = len(script) - offset params = script[offset : offset + dataLength] if ((offset + dataLength) == len(script)): params.extend(sequence) apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_HASH_INPUT_START, 0x80, 0x00, len(params) ] apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset += blockLength if len(script) == 0: apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_HASH_INPUT_START, 0x80, 0x00, len(sequence) ] apdu.extend(sequence) self.dongle.exchange(bytearray(apdu)) currentIndex += 1
def startUntrustedTransaction(self, newTransaction, inputIndex, outputList, redeemScript, version=0x02, overwintered=False): # Start building a fake transaction with the passed inputs if newTransaction: if overwintered: p2 = 0x05 if version == 4 else 0x04 else: p2 = 0x00 else: p2 = 0x80 apdu = [self.BTCHIP_CLA, self.BTCHIP_INS_HASH_INPUT_START, 0x00, p2] if overwintered and version == 3: params = bytearray( [version, 0x00, 0x00, 0x80, 0x70, 0x82, 0xc4, 0x03]) elif overwintered and version == 4: params = bytearray( [version, 0x00, 0x00, 0x80, 0x85, 0x20, 0x2f, 0x89]) else: params = bytearray([version, 0x00, 0x00, 0x00]) writeVarint(len(outputList), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) # Loop for each input currentIndex = 0 for passedOutput in outputList: if ('sequence' in passedOutput) and passedOutput['sequence']: sequence = bytearray(unhexlify(passedOutput['sequence'])) else: sequence = bytearray([0xFF, 0xFF, 0xFF, 0xFF]) # default sequence apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_HASH_INPUT_START, 0x80, 0x00 ] params = [] script = bytearray(redeemScript) if overwintered: params.append(0x02) elif ('trustedInput' in passedOutput) and passedOutput['trustedInput']: params.append(0x01) else: params.append(0x00) if ('trustedInput' in passedOutput) and passedOutput['trustedInput']: params.append(len(passedOutput['value'])) params.extend(passedOutput['value']) if currentIndex != inputIndex: script = bytearray() writeVarint(len(script), params) if len(script) == 0: params.extend(sequence) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset = 0 while (offset < len(script)): blockLength = 255 if ((offset + blockLength) < len(script)): dataLength = blockLength else: dataLength = len(script) - offset params = script[offset:offset + dataLength] if ((offset + dataLength) == len(script)): params.extend(sequence) apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_HASH_INPUT_START, 0x80, 0x00, len(params) ] apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset += blockLength currentIndex += 1
def serializeOutputs(self): result = [] writeVarint(len(self.outputs), result) for troutput in self.outputs: result.extend(troutput.serialize()) return result
def getTrustedInput(self, transaction, index): result = {} # Header apdu = [self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x00, 0x00] params = bytearray.fromhex("%.8x" % (index)) params.extend(transaction.version) writeVarint(len(transaction.inputs), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) # Each input for trinput in transaction.inputs: apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00 ] params = bytearray(trinput.prevOut) writeVarint(len(trinput.script), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset = 0 while True: blockLength = 251 if ((offset + blockLength) < len(trinput.script)): dataLength = blockLength else: dataLength = len(trinput.script) - offset params = bytearray(trinput.script[offset:offset + dataLength]) if ((offset + dataLength) == len(trinput.script)): params.extend(trinput.sequence) apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00, len(params) ] apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset += dataLength if (offset >= len(trinput.script)): break # Number of outputs apdu = [self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00] params = [] writeVarint(len(transaction.outputs), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) # Each output indexOutput = 0 for troutput in transaction.outputs: apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00 ] params = bytearray(troutput.amount) writeVarint(len(troutput.script), params) apdu.append(len(params)) apdu.extend(params) self.dongle.exchange(bytearray(apdu)) offset = 0 while (offset < len(troutput.script)): blockLength = 255 if ((offset + blockLength) < len(troutput.script)): dataLength = blockLength else: dataLength = len(troutput.script) - offset apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00, dataLength ] apdu.extend(troutput.script[offset:offset + dataLength]) self.dongle.exchange(bytearray(apdu)) offset += dataLength params = [] apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_GET_TRUSTED_INPUT, 0x80, 0x00, len(transaction.lockTime) + len(params) ] # Locktime apdu.extend(transaction.lockTime) apdu.extend(params) response = self.dongle.exchange(bytearray(apdu)) result['trustedInput'] = True result['value'] = response return result