def deserialize(txhex): t = etr.deserialize(txhex) #translation from Electrum deserialization #to pybitcointools form as used in joinmarket #pybitcointools structure: #obj = {"ins": [..], "outs": [..], "locktime": int} #where ins elements are: #{"outpoint": {"hash": bigendian32,"index": int}, #"script": hex,"sequence": int} #and outs elements are: #{"script": hex, "value": int} # #while electrum.transaction.deserialize returns object #like: #{"version": int, "inputs": [..], "outputs": [..], "lockTime": int} obj = {} obj["version"] = t["version"] obj["locktime"] = t["lockTime"] obj["ins"] = [] obj["outs"] = [] for i in t["inputs"]: outpoint = {"hash": i["prevout_hash"], "index": i["prevout_n"]} scr = i["scriptSig"] sequence = i["sequence"] obj["ins"].append({"outpoint": outpoint, "script": scr, "sequence": sequence}) for i in t["outputs"]: obj["outs"].append({"script": i["scriptPubKey"], "value": i["value"]}) return obj
def deserialize(txhex): t = etr.deserialize(txhex) #translation from Electrum deserialization #to pybitcointools form as used in joinmarket #pybitcointools structure: #obj = {"ins": [..], "outs": [..], "locktime": int} #where ins elements are: #{"outpoint": {"hash": bigendian32,"index": int}, #"script": hex,"sequence": int} #and outs elements are: #{"script": hex, "value": int} # #while electrum.transaction.deserialize returns object #like: #{"version": int, "inputs": [..], "outputs": [..], "lockTime": int} obj = {} obj["version"] = t["version"] obj["locktime"] = t["lockTime"] obj["ins"] = [] obj["outs"] = [] for i in t["inputs"]: outpoint = {"hash": i["prevout_hash"], "index": i["prevout_n"]} scr = i["scriptSig"] sequence = i["sequence"] obj["ins"].append({ "outpoint": outpoint, "script": scr, "sequence": sequence }) for i in t["outputs"]: obj["outs"].append({ "script": i["scriptPubKey"], "value": i["value"] }) return obj
def electrum_tx_to_txtype(self, tx): t = self.types.TransactionType() d = deserialize(tx.raw) t.version = d['version'] t.lock_time = d['lockTime'] inputs = self.tx_inputs(tx) t.inputs.extend(inputs) for vout in d['outputs']: o = t.bin_outputs.add() o.amount = vout['value'] o.script_pubkey = bfh(vout['scriptPubKey']) return t
def electrum_tx_to_txtype(self, tx): t = types.TransactionType() d = deserialize(tx.raw) t.version = d["version"] t.lock_time = d["lockTime"] inputs = self.tx_inputs(tx) t.inputs.extend(inputs) for vout in d["outputs"]: o = t.bin_outputs.add() o.amount = vout["value"] o.script_pubkey = vout["scriptPubKey"].decode("hex") return t
def electrum_tx_to_txtype(self, tx, xpub_path): t = TransactionType() if tx is None: # probably for segwit input and we don't need this prev txn return t d = deserialize(tx.raw) t.version = d['version'] t.lock_time = d['lockTime'] t.inputs = self.tx_inputs(tx, xpub_path) t.bin_outputs = [ TxOutputBinType(amount=vout['value'], script_pubkey=bfh(vout['scriptPubKey'])) for vout in d['outputs'] ] return t
def electrum_tx_to_txtype(self, tx): t = self.types.TransactionType() if tx is None: # probably for segwit input and we don't need this prev txn return t d = deserialize(tx.raw) t.version = d['version'] t.lock_time = d['lockTime'] inputs = self.tx_inputs(tx) t._extend_inputs(inputs) for vout in d['outputs']: o = t._add_bin_outputs() o.amount = vout['value'] o.script_pubkey = bfh(vout['scriptPubKey']) return t
def test_tx_unsigned(self): self.maxDiff = None expected = { 'inputs': [{ 'type': 'p2pkh', 'address': '14iRdacqJ95JffkUFUTUoZmHCUkq21UMAZ', 'issuance': None, 'num_sig': 1, 'prevout_hash': '25554b1cb7c28ca28188066312f66524bf1b241a120dec8bd39e81699aebddf8', 'prevout_n': 1, 'pubkeys': [ '031ec67b31750c9ca58b859200267625681d4c9849f8fb163207c4186a273e0b0a' ], 'scriptSig': '01ff4c53ff0488b21e000000000000000000350138c626aac760ea9eedb47287f12c4d783910821c5602d5f8ed933a8f0d95025fb1f45ecb87f2089dc8b0257fc23cc5fd13ae9d4e14c08b0398002d68eae14c00000000', 'sequence': 4294967294, 'signatures': [None], 'x_pubkeys': [ 'ff0488b21e000000000000000000350138c626aac760ea9eedb47287f12c4d783910821c5602d5f8ed933a8f0d95025fb1f45ecb87f2089dc8b0257fc23cc5fd13ae9d4e14c08b0398002d68eae14c00000000' ] }], 'lockTime': 3, 'outputs': [{ 'address': '1BvbZykUE5oS5ACH5U4mhwE5KdJPHson7', 'asset': '6718fdfa571f3f3d091cf57f03ceac534ee5a4f78f80880dc97ee1b4f5c21da4', 'asset_version': 1, 'nonce': None, 'nonce_version': 0, 'prevout_n': 0, 'scriptPubKey': '76a9140210e63973f9feddf155e5e73ac8f7289549b5f788ac', 'range_proof': None, 'surjection_proof': None, 'type': TYPE_ADDRESS, 'value': 100000000000000, 'value_version': 1 }, { 'address': '1FRUENS6LR8JdwEoptZwjRA1c64WDgcsac', 'asset': '6718fdfa571f3f3d091cf57f03ceac534ee5a4f78f80880dc97ee1b4f5c21da4', 'asset_version': 1, 'nonce': None, 'nonce_version': 0, 'prevout_n': 1, 'scriptPubKey': '76a9149e327995acc97229c07ce5e75789dab5eb3b689188ac', 'range_proof': None, 'surjection_proof': None, 'type': TYPE_ADDRESS, 'value': 399999999965500, 'value_version': 1 }, { 'address': '', 'asset': '6718fdfa571f3f3d091cf57f03ceac534ee5a4f78f80880dc97ee1b4f5c21da4', 'asset_version': 1, 'nonce': None, 'nonce_version': 0, 'prevout_n': 2, 'scriptPubKey': '', 'range_proof': None, 'surjection_proof': None, 'type': TYPE_SCRIPT, 'value': 34500, 'value_version': 1 }], 'partial': True, 'segwit_ser': False, 'version': 1, } tx = transaction.Transaction(unsigned_blob) self.assertEqual(tx.deserialize(), expected) self.assertEqual(tx.deserialize(), None) self.assertEqual(tx.as_dict(), { 'hex': unsigned_blob, 'complete': False, 'final': True }) self.assertEqual(tx.get_outputs(), [ ('1BvbZykUE5oS5ACH5U4mhwE5KdJPHson7', 100000000000000, '6718fdfa571f3f3d091cf57f03ceac534ee5a4f78f80880dc97ee1b4f5c21da4' ), ('1FRUENS6LR8JdwEoptZwjRA1c64WDgcsac', 399999999965500, '6718fdfa571f3f3d091cf57f03ceac534ee5a4f78f80880dc97ee1b4f5c21da4' ), ('SCRIPT ', 34500, '6718fdfa571f3f3d091cf57f03ceac534ee5a4f78f80880dc97ee1b4f5c21da4' ) ]) self.assertEqual(tx.get_output_addresses(), [ '1BvbZykUE5oS5ACH5U4mhwE5KdJPHson7', '1FRUENS6LR8JdwEoptZwjRA1c64WDgcsac', 'SCRIPT ' ]) self.assertTrue(tx.has_address('1BvbZykUE5oS5ACH5U4mhwE5KdJPHson7')) self.assertTrue(tx.has_address('1FRUENS6LR8JdwEoptZwjRA1c64WDgcsac')) self.assertFalse(tx.has_address('1FRUENS6LR8JdwEoptZwjRA1c64WDgcsab')) self.assertEqual(tx.serialize(), unsigned_blob) tx.update_signatures(signed_blob_signatures) self.assertEqual(tx.raw, signed_blob) tx.update(unsigned_blob) tx.raw = None blob = str(tx) self.assertEqual(transaction.deserialize(blob), expected)