def insight_tx(url): try: f = urllib2.urlopen(url) except: raise Exception('URL error: %s' % url) data = json.load(f) t = proto_types.TransactionType() t.version = data['version'] t.lock_time = data['locktime'] for vin in data['vin']: i = t.inputs.add() if 'coinbase' in vin.keys(): i.prev_hash = "\0" * 32 i.prev_index = 0xffffffff # signed int -1 i.script_sig = binascii.unhexlify(vin['coinbase']) i.sequence = vin['sequence'] else: i.prev_hash = binascii.unhexlify(vin['txid']) i.prev_index = vin['vout'] asm = vin['scriptSig']['asm'].split(' ') asm = [opcode_serialize(x) for x in asm] i.script_sig = ''.join(asm) i.sequence = vin['sequence'] for vout in data['vout']: o = t.bin_outputs.add() o.amount = int(Decimal(vout['value']) * 100000000) asm = vout['scriptPubKey']['asm'].split(' ') asm = [opcode_serialize(x) for x in asm] o.script_pubkey = ''.join(asm) return t
def insight_tx(url, rawdata=False): if not rawdata: try: f = urllib2.urlopen(url) data = json.load(f) except: raise Exception('URL error: %s' % url) else: data = url t = proto_types.TransactionType() t.version = data['version'] t.lock_time = data['locktime'] for vin in data['vin']: i = t.inputs.add() if 'coinbase' in vin.keys(): i.prev_hash = "\0" * 32 i.prev_index = 0xffffffff # signed int -1 i.script_sig = binascii.unhexlify(vin['coinbase']) i.sequence = vin['sequence'] else: i.prev_hash = binascii.unhexlify(vin['txid']) i.prev_index = vin['vout'] i.script_sig = binascii.unhexlify(vin['scriptSig']['hex']) i.sequence = vin['sequence'] for vout in data['vout']: o = t.bin_outputs.add() o.amount = int(Decimal(str(vout['value'])) * 100000000) o.script_pubkey = binascii.unhexlify(vout['scriptPubKey']['hex']) return t
def _prepare_sign_tx(self, coin_name, inputs, outputs): tx = types.TransactionType() tx.inputs.extend(inputs) tx.outputs.extend(outputs) txes = {} txes[''] = tx known_hashes = [] for inp in inputs: if inp.prev_hash in known_hashes: continue txes[inp.prev_hash] = self.tx_api.get_tx( binascii.hexlify(inp.prev_hash)) known_hashes.append(inp.prev_hash) return txes
def sign_tx(self, coin_name, inputs, outputs, debug_processor=None): start = time.time() txes = self._prepare_sign_tx(coin_name, inputs, outputs) try: self.transport.session_begin() # Prepare and send initial message tx = proto.SignTx() tx.inputs_count = len(inputs) tx.outputs_count = len(outputs) tx.coin_name = coin_name res = self.call(tx) # Prepare structure for signatures signatures = [None] * len(inputs) serialized_tx = '' counter = 0 while True: counter += 1 if isinstance(res, proto.Failure): raise CallException("Signing failed") if not isinstance(res, proto.TxRequest): raise CallException("Unexpected message") # If there's some part of signed transaction, let's add it if res.HasField('serialized') and res.serialized.HasField( 'serialized_tx'): log("RECEIVED PART OF SERIALIZED TX (%d BYTES)" % len(res.serialized.serialized_tx)) serialized_tx += res.serialized.serialized_tx if res.HasField('serialized') and res.serialized.HasField( 'signature_index'): if signatures[res.serialized.signature_index] != None: raise Exception( "Signature for index %d already filled" % res.serialized.signature_index) signatures[res.serialized. signature_index] = res.serialized.signature if res.request_type == types.TXFINISHED: # Device didn't ask for more information, finish workflow break # Device asked for one more information, let's process it. current_tx = txes[res.details.tx_hash] if res.request_type == types.TXMETA: msg = types.TransactionType() msg.version = current_tx.version msg.lock_time = current_tx.lock_time msg.inputs_cnt = len(current_tx.inputs) if res.details.tx_hash: msg.outputs_cnt = len(current_tx.bin_outputs) else: msg.outputs_cnt = len(current_tx.outputs) res = self.call(proto.TxAck(tx=msg)) continue elif res.request_type == types.TXINPUT: msg = types.TransactionType() msg.inputs.extend([ current_tx.inputs[res.details.request_index], ]) res = self.call(proto.TxAck(tx=msg)) continue elif res.request_type == types.TXOUTPUT: msg = types.TransactionType() if res.details.tx_hash: msg.bin_outputs.extend([ current_tx.bin_outputs[res.details.request_index], ]) else: msg.outputs.extend([ current_tx.outputs[res.details.request_index], ]) if debug_processor != None: # If debug_processor function is provided, # pass thru it the request and prepared response. # This is useful for unit tests, see test_msg_signtx msg = debug_processor(res, msg) res = self.call(proto.TxAck(tx=msg)) continue finally: self.transport.session_end() if None in signatures: raise Exception("Some signatures are missing!") log("SIGNED IN %.03f SECONDS, CALLED %d MESSAGES, %d BYTES" % \ (time.time() - start, counter, len(serialized_tx))) return (signatures, serialized_tx)