示例#1
0
    def test_change_tx_fields(self):
        tx = Transaction.deserialize(maza_raw_tx)

        chainparams.set_tx_fields(peercoin_fields)
        tx2 = Transaction.deserialize(ppc_raw_tx)

        self.assertNotEqual(tx.fields, tx2.fields)
示例#2
0
def abe_parse_raw_tx(res):
    version = int(res.get('ver'))
    locktime = int(res.get('lock_time'))
    vin = []
    vout = []
    for i in res.get('in'):
        prev_txid = i['prev_out']['hash']
        prev_n = int(i['prev_out']['n'])
        tx_outpoint = COutPoint(lx(prev_txid), prev_n)

        scriptSig = Script(x( i['raw_scriptSig'] ))
        sequence = int(i['sequence'])
        
        tx_input = CTxIn(tx_outpoint, x(scriptSig.get_hex()), sequence)
        vin.append(tx_input)

    for o in res.get('out'):
        value = float(o['value'])
        value = int(value * pow(10, 8))

        script = Script(x( o['raw_scriptPubKey'] ))
        tx_output = CTxOut(value, x(script.get_hex()))
        vout.append(tx_output)

    tx = Transaction(vin, vout, locktime, version)
    return b2x(tx.serialize())
示例#3
0
def insight_parse_raw_tx(res):
    version = int(res.get('version'))
    locktime = int(res.get('locktime'))
    vin = []
    vout = []
    for i in res.get('vin'):
        prev_txid = i['txid']
        prev_n = int(i['n'])

        seq = int(i['sequence'])
        script_asm = i['scriptSig']['asm']
        script = Script.from_human(script_asm)

        tx_outpoint = COutPoint(lx(prev_txid), prev_n)
        tx_input = CTxIn(tx_outpoint, x(script.get_hex()), seq)
        vin.append(tx_input)

    for o in res.get('vout'):
        value = float(o['value'])
        value = int(value * pow(10, 8))

        script_asm = o['scriptPubKey']['asm']
        script = Script.from_human(script_asm)

        tx_output = CTxOut(value, x(script.get_hex()))
        vout.append(tx_output)

    tx = Transaction(vin, vout, locktime, version)
    return b2x(tx.serialize())
示例#4
0
 def test_from_tx_with_transaction_argument(self):
     tx = Transaction()
     chainparams.set_to_preset('Peercoin')
     self.assertRaises(AttributeError, getattr, tx, 'Timestamp')
     tx2 = Transaction.from_tx(tx)
     self.assertIsNot(tx, tx2)
     self.assertEqual(tx2.Timestamp, 0)
示例#5
0
    def test_change_tx_fields(self):
        tx = Transaction.deserialize(maza_raw_tx)

        chainparams.set_tx_fields(peercoin_fields)
        tx2 = Transaction.deserialize(ppc_raw_tx)

        self.assertNotEqual(tx.fields, tx2.fields)
示例#6
0
    def test_preset_chainparams(self):
        chainparams.set_to_preset('Bitcoin')
        tx = Transaction.deserialize(maza_raw_tx)
        self.assertRaises(Exception, Transaction.deserialize, clams_raw_tx)
        self.assertRaises(Exception, Transaction.deserialize, ppc_raw_tx)

        chainparams.set_to_preset('Clams')
        tx = Transaction.deserialize(clams_raw_tx)
        self.assertRaises(Exception, Transaction.deserialize, maza_raw_tx)

        chainparams.set_to_preset('Peercoin')
        tx = Transaction.deserialize(ppc_raw_tx)
        self.assertRaises(Exception, Transaction.deserialize, clams_raw_tx)
        self.assertRaises(Exception, Transaction.deserialize, maza_raw_tx)
示例#7
0
    def test_preset_chainparams(self):
        chainparams.set_to_preset('Bitcoin')
        tx = Transaction.deserialize(maza_raw_tx)
        self.assertRaises(Exception, Transaction.deserialize, clams_raw_tx)
        self.assertRaises(Exception, Transaction.deserialize, ppc_raw_tx)

        chainparams.set_to_preset('Clams')
        tx = Transaction.deserialize(clams_raw_tx)
        self.assertRaises(Exception, Transaction.deserialize, maza_raw_tx)

        chainparams.set_to_preset('Peercoin')
        tx = Transaction.deserialize(ppc_raw_tx)
        self.assertRaises(Exception, Transaction.deserialize, clams_raw_tx)
        self.assertRaises(Exception, Transaction.deserialize, maza_raw_tx)
示例#8
0
    def check_raw_tx(self):
        txt = str(self.raw_tx_edit.toPlainText())
        # Variable substitution
        if txt.startswith('$'):
            var_value = self.handler.get_plugin('Variables').dock.get_key(
                txt[1:])
            if var_value:
                self.raw_tx_edit.setPlainText(var_value)
            return
        tx = None
        valid = True
        try:
            tx = Transaction.deserialize(txt.decode('hex'))
        except Exception:
            valid = False

        self.tx = tx
        self.deserialize_button.setEnabled(valid)
        self.inputs_box.setEnabled(valid)
        self.verify_button.setEnabled(valid)
        self.verify_all_button.setEnabled(valid)
        self.tx_widget.setEnabled(valid)
        self.clear()
        if valid:
            self.raw_tx_invalid.hide()
            self.inputs_box.setRange(0, len(tx.vin) - 1)
            self.deserialize()
        elif txt:
            self.raw_tx_invalid.show()
        else:
            self.raw_tx_invalid.hide()
示例#9
0
    def do_verify_input(self, tx, in_idx):
        raw_prev_tx = None
        tx_in = tx.vin[in_idx]
        txid = b2lx(tx_in.prevout.hash)
        prev_out_n = tx_in.prevout.n

        try:
            raw_prev_tx = self.handler.download_blockchain_data(
                'raw_transaction', txid)
        except Exception as e:
            self.status_message(str(e), True)
            return False

        try:
            prev_tx = Transaction.deserialize(raw_prev_tx.decode('hex'))
            result = bitcoin.core.scripteval.VerifyScript(
                tx_in.scriptSig, prev_tx.vout[prev_out_n].scriptPubKey, tx,
                in_idx)
            self.result_edit.setText(
                'Successfully verified input {}'.format(in_idx))
            self.inputs_table.set_verified(in_idx, True)
        except Exception as e:
            self.result_edit.setText(str(e))
            self.inputs_table.set_verified(in_idx, False)
            self.status_message(str(e), True)
            return False

        return True
示例#10
0
 def test_from_tx_with_transaction_argument(self):
     tx = Transaction()
     chainparams.set_to_preset('Peercoin')
     self.assertRaises(AttributeError, getattr, tx, 'Timestamp')
     tx2 = Transaction.from_tx(tx)
     self.assertIsNot(tx, tx2)
     self.assertEqual(tx2.Timestamp, 0)
示例#11
0
 def __init__(self, tx=None, parent=None):
     super(OutputsModel, self).__init__(parent)
     if tx is None:
         tx = Transaction()
     self.tx = tx
     self.amount_format = config.get_config().get_option(
         'amount_format', 'coins')
示例#12
0
    def check_raw_tx(self):
        txt = str(self.raw_tx_edit.toPlainText())
        # Variable substitution
        if txt.startswith('$'):
            var_value = self.handler.get_plugin('Variables').ui.get_key(txt[1:])
            if var_value:
                self.raw_tx_edit.setPlainText(var_value)
            return
        tx = None
        valid = True
        try:
            tx = Transaction.deserialize(txt.decode('hex'))
        except Exception:
            valid = False

        self.tx = tx
        self.deserialize_button.setEnabled(valid)
        self.inputs_box.setEnabled(valid)
        self.verify_button.setEnabled(valid)
        self.verify_all_button.setEnabled(valid)
        self.tx_widget.setEnabled(valid)
        self.clear()
        if valid:
            self.raw_tx_invalid.hide()
            self.inputs_box.setRange(0, len(tx.vin) - 1)
            self.deserialize()
        elif txt:
            self.raw_tx_invalid.show()
        else:
            self.raw_tx_invalid.hide()
示例#13
0
文件: stack.py 项目: oktoshi/hashmal
 def set_tx(self):
     """Set the spending transaction and (en|dis)able the input index box."""
     txt = str(self.tx_edit.toPlainText())
     try:
         assert txt
         self.tx = Transaction.deserialize(txt.decode('hex'))
         self.tx_edit.setToolTip(''.join(['Tx ID: ', bitcoin.core.b2lx(self.tx.GetHash())]))
         self.input_idx.setRange(0, len(self.tx.vin) - 1)
         self.input_idx.setEnabled(True)
     except Exception:
         self.tx = None
         self.tx_edit.setToolTip('')
         self.input_idx.setEnabled(False)
示例#14
0
 def test_init_with_field_keyword_args(self):
     ins = (
         CTxIn(COutPoint(lx('537ecb89e5ed7e872f988447432e6791c0a58b069c4ec8647e1683a383e867a3'), 0),
               x('473044022043b9aee9187effd7e6c7bc444b09162570f17e36b4a9c02cf722126cc0efa3d502200b3ba14c809fa9a6f7f835cbdbbb70f2f43f6b30beaf91eec6b8b5981c80cea50121025edf500f18f9f2b3f175f823fa996fbb2ec52982a9aeb1dc2e388a651054fb0f'))
     )
     outs = (
         CTxOut(114263, x('76a91495efca2c6a6f0e0f0ce9530219b48607a962e77788ac')),
         CTxOut(2125893, x('76a914f28abfb465126d6772dcb4403b9e1ad2ea28a03488ac'))
     )
     fields_data = {'Timestamp': 1432478808}
     tx = Transaction(ins, outs, 0, 2, peercoin_fields, fields_data)
     self.assertEqual(tx.fields, peercoin_fields)
     self.assertEqual(tx.Timestamp, 1432478808)
示例#15
0
    def verify_input(self):
        tx = None
        try:
            txt = str(self.raw_tx_edit.toPlainText())
            tx = Transaction.deserialize(txt.decode('hex'))
        except Exception:
            self.status_message('Could not deserialize transaction.', True)
            return
        in_idx = self.inputs_box.value()
        if in_idx >= len(tx.vin):
            self.status_message('Input {} does not exist.'.format(in_idx), True)
            return

        self.do_verify_input(tx, in_idx)
示例#16
0
 def set_tx(self):
     """Set the spending transaction and (en|dis)able the input index box."""
     txt = str(self.tx_edit.toPlainText())
     try:
         assert txt
         self.tx = Transaction.deserialize(txt.decode('hex'))
         self.tx_edit.setToolTip(''.join(
             ['Tx ID: ', bitcoin.core.b2lx(self.tx.GetHash())]))
         self.input_idx.setRange(0, len(self.tx.vin) - 1)
         self.input_idx.setEnabled(True)
     except Exception:
         self.tx = None
         self.tx_edit.setToolTip('')
         self.input_idx.setEnabled(False)
示例#17
0
    def verify_input(self):
        tx = None
        try:
            txt = str(self.raw_tx_edit.toPlainText())
            tx = Transaction.deserialize(txt.decode('hex'))
        except Exception:
            self.status_message('Could not deserialize transaction.', True)
            return
        in_idx = self.inputs_box.value()
        if in_idx >= len(tx.vin):
            self.status_message('Input {} does not exist.'.format(in_idx),
                                True)
            return

        self.do_verify_input(tx, in_idx)
示例#18
0
    def classify_data(self, value):
        """Determine what to categorize a value as."""
        # If the value is not hex, assume text
        try:
            i = int(value, 16)
        except ValueError:
            return 'Text'

        # See if it's a raw transaction.
        try:
            t = Transaction.deserialize(value.decode('hex'))
            return 'Raw Transaction'
        except Exception:
            pass

        # Use the generic 'Hex' category if nothing else matches.
        return 'Hex'
示例#19
0
    def classify_data(self, value):
        """Determine what to categorize a value as."""
        # If the value is not hex, assume text
        try:
            i = int(value, 16)
        except ValueError:
            return 'Text'

        # See if it's a raw transaction.
        try:
            t = Transaction.deserialize(value.decode('hex'))
            return 'Raw Transaction'
        except Exception:
            pass

        # Use the generic 'Hex' category if nothing else matches.
        return 'Hex'
示例#20
0
    def do_verify_inputs(self, txt):
        self.needsFocus.emit()
        self.raw_tx_edit.setPlainText(txt)
        tx = Transaction.deserialize(txt.decode('hex'))
        failed_inputs = []
        self.result_edit.setText('Verifying...')
        for i in range(len(tx.vin)):
            if not self.do_verify_input(tx, i):
                failed_inputs.append(i)

        result = 'Successfully verified all inputs.'
        ret_val = True
        if failed_inputs:
            result = 'Failed to verify inputs: {}'.format(failed_inputs)
            ret_val = False
        if len(tx.vin) == 0:
            result = 'Transaction has no inputs.'
        self.result_edit.setText(result)
        return ret_val
示例#21
0
    def do_verify_inputs(self, txt):
        self.needsFocus.emit()
        self.raw_tx_edit.setPlainText(txt)
        tx = Transaction.deserialize(txt.decode('hex'))
        failed_inputs = []
        self.result_edit.setText('Verifying...')
        for i in range(len(tx.vin)):
            if not self.do_verify_input(tx, i):
                failed_inputs.append(i)

        result = 'Successfully verified all inputs.'
        ret_val = True
        if failed_inputs:
            result = 'Failed to verify inputs: {}'.format(failed_inputs)
            ret_val = False
        if len(tx.vin) == 0:
            result = 'Transaction has no inputs.'
        self.result_edit.setText(result)
        return ret_val
示例#22
0
 def set_tx(self):
     """Set the spending transaction and (en|dis)able the input index box."""
     txt = str(self.tx_edit.toPlainText())
     # Variable substition
     if txt.startswith('$'):
         var_value = self.handler.get_plugin('Variables').ui.get_key(txt[1:])
         if var_value:
             self.tx_edit.setPlainText(var_value)
             return
     try:
         assert txt
         self.tx = Transaction.deserialize(txt.decode('hex'))
         self.tx_edit.setToolTip(''.join(['Tx ID: ', bitcoin.core.b2lx(self.tx.GetHash())]))
         self.input_idx.setRange(0, len(self.tx.vin) - 1)
         self.input_idx.setEnabled(True)
     except Exception:
         self.tx = None
         self.tx_edit.setToolTip('')
         self.input_idx.setEnabled(False)
示例#23
0
    def build_transaction(self):
        self.tx_widget.clear()
        self.tx = tx = Transaction()
        tx.nVersion = self.version_edit.get_amount()
        tx.vin = self.inputs_tree.get_inputs()
        tx.vout = self.outputs_tree.get_outputs()
        tx.nLockTime = self.locktime_edit.get_amount()

        for name, w in self.tx_field_widgets:
            if not name in [field[0] for field in tx.fields]:
                continue
            value = str(w.text())
            default = getattr(tx, name)
            if isinstance(default, int):
                value = w.get_amount()
            setattr(tx, name, value)

        self.raw_tx.setText(bitcoin.core.b2x(tx.serialize()))

        self.tx_widget.set_tx(tx)
示例#24
0
 def deserialize_raw(self, rawtx):
     """Update editor widgets with rawtx's data."""
     self.needsFocus.emit()
     try:
         tx = Transaction.deserialize(x(rawtx))
     except Exception:
         return
     else:
         self.version_edit.set_amount(tx.nVersion)
         self.inputs_tree.model.set_tx(tx)
         self.outputs_tree.model.set_tx(tx)
         self.locktime_edit.set_amount(tx.nLockTime)
         for name, w in self.tx_field_widgets:
             if name in ["nVersion", "vin", "vout", "nLockTime"]:
                 continue
             value = getattr(tx, name)
             if isinstance(w, AmountEdit):
                 w.set_amount(value)
             else:
                 w.setText(str(value))
         self.build_transaction()
示例#25
0
 def deserialize_raw(self, rawtx):
     """Update editor widgets with rawtx's data."""
     self.needsFocus.emit()
     try:
         tx = Transaction.deserialize(x(rawtx))
     except Exception:
         return
     else:
         self.version_edit.set_amount(tx.nVersion)
         self.inputs_tree.model.set_tx(tx)
         self.outputs_tree.model.set_tx(tx)
         self.locktime_edit.set_amount(tx.nLockTime)
         for name, w in self.tx_field_widgets:
             if name in ['nVersion', 'vin', 'vout', 'nLockTime']:
                 continue
             value = getattr(tx, name)
             if isinstance(w, AmountEdit):
                 w.set_amount(value)
             else:
                 w.setText(str(value))
         self.build_transaction()
示例#26
0
    def check_raw_tx(self):
        txt = str(self.raw_tx_edit.toPlainText())
        tx = None
        valid = True
        try:
            tx = Transaction.deserialize(txt.decode('hex'))
        except Exception:
            valid = False

        self.tx = tx
        self.deserialize_button.setEnabled(valid)
        self.inputs_box.setEnabled(valid)
        self.verify_button.setEnabled(valid)
        self.verify_all_button.setEnabled(valid)
        self.tx_widget.setEnabled(valid)
        self.clear()
        if valid:
            self.raw_tx_invalid.hide()
            self.inputs_box.setRange(0, len(tx.vin) - 1)
            self.deserialize()
        elif txt:
            self.raw_tx_invalid.show()
        else:
            self.raw_tx_invalid.hide()
示例#27
0
    def do_verify_input(self, tx, in_idx):
        raw_prev_tx = None
        tx_in = tx.vin[in_idx]
        txid = b2lx(tx_in.prevout.hash)
        prev_out_n = tx_in.prevout.n

        try:
            raw_prev_tx = self.handler.download_blockchain_data('raw_transaction', txid)
        except Exception as e:
            self.status_message(str(e), True)
            return False

        try:
            prev_tx = Transaction.deserialize(raw_prev_tx.decode('hex'))
            result = bitcoin.core.scripteval.VerifyScript(tx_in.scriptSig, prev_tx.vout[prev_out_n].scriptPubKey, tx, in_idx)
            self.result_edit.setText('Successfully verified input {}'.format(in_idx))
            self.inputs_table.set_verified(in_idx, True)
        except Exception as e:
            self.result_edit.setText(str(e))
            self.inputs_table.set_verified(in_idx, False)
            self.status_message(str(e), True)
            return False

        return True
示例#28
0
    def check_raw_tx(self):
        txt = str(self.raw_tx_edit.toPlainText())
        tx = None
        valid = True
        try:
            tx = Transaction.deserialize(txt.decode('hex'))
        except Exception:
            valid = False

        self.tx = tx
        self.deserialize_button.setEnabled(valid)
        self.inputs_box.setEnabled(valid)
        self.verify_button.setEnabled(valid)
        self.verify_all_button.setEnabled(valid)
        self.tx_widget.setEnabled(valid)
        self.clear()
        if valid:
            self.raw_tx_invalid.hide()
            self.inputs_box.setRange(0, len(tx.vin) - 1)
            self.deserialize()
        elif txt:
            self.raw_tx_invalid.show()
        else:
            self.raw_tx_invalid.hide()
示例#29
0
def is_raw_tx(x):
    try:
        t = Transaction.deserialize(x.decode('hex'))
        return True
    except Exception:
        return False
示例#30
0
 def copy_txid(rawtx):
     txid = b2lx(Transaction.deserialize(x(rawtx)).GetHash())
     QApplication.clipboard().setText(txid)
示例#31
0
 def clear(self):
     self.set_tx(Transaction())
示例#32
0
 def coerce_tx(v):
     return Transaction.from_tx(v)
示例#33
0
 def coerce_hex_string(v):
     return Transaction.deserialize(x(v))
示例#34
0
 def test_serialize_as_hex(self):
     tx = Transaction.deserialize(maza_raw_tx)
     self.assertEqual(maza_raw_tx.encode('hex'), tx.as_hex())
示例#35
0
 def set_tx(self, tx):
     """Reset the model to reflect tx."""
     self.beginResetModel()
     self.tx = Transaction.from_tx(tx)
     self.endResetModel()
示例#36
0
 def test_serialize_as_hex(self):
     tx = Transaction.deserialize(maza_raw_tx)
     self.assertEqual(maza_raw_tx.encode('hex'), tx.as_hex())
示例#37
0
 def test_peercoin_fields(self):
     chainparams.set_tx_fields(peercoin_fields)
     tx = Transaction.deserialize(ppc_raw_tx)
     self.assertNotEqual(bitcoin_fields, tx.fields)
     self.assertIn(('Timestamp', b'<i', 4, 0), tx.fields)
     self.assertEqual(ppc_raw_tx, tx.serialize())
示例#38
0
 def test_clams_fields(self):
     chainparams.set_tx_fields(clams_fields)
     tx = Transaction.deserialize(clams_raw_tx)
     self.assertNotEqual(bitcoin_fields, tx.fields)
     self.assertIn(('ClamSpeech', 'bytes', None, b''), tx.fields)
     self.assertEqual(clams_raw_tx, tx.serialize())
示例#39
0
 def test_bitcoin_fields(self):
     tx = Transaction.deserialize(maza_raw_tx)
     self.assertEqual(bitcoin_fields, tx.fields)
     self.assertEqual(maza_raw_tx, tx.serialize())
示例#40
0
 def test_clams_fields(self):
     chainparams.set_tx_fields(clams_fields)
     tx = Transaction.deserialize(clams_raw_tx)
     self.assertNotEqual(bitcoin_fields, tx.fields)
     self.assertIn(('ClamSpeech', 'bytes', None, b''), tx.fields)
     self.assertEqual(clams_raw_tx, tx.serialize())
 def test_get_unsigned_outputs_with_sighash_all(self):
     tx = Transaction.deserialize(x(raw_tx_sighash_all))
     unsigned = get_unsigned_outputs(tx)
     self.assertEqual([], unsigned)
示例#42
0
 def __init__(self, tx=None, parent=None):
     super(InputsModel, self).__init__(parent)
     if tx is None:
         tx = Transaction()
     self.tx = tx
示例#43
0
 def test_chainparams_tx_serializer(self):
     chainparams.set_to_preset('Clams')
     tx = Transaction.deserialize(clams_raw_tx)
     self.assertEqual(clams_raw_tx, tx.serialize())
     tx2 = Transaction.deserialize(clams_v1_raw_tx)
     self.assertEqual(clams_v1_raw_tx, tx2.serialize())
 def test_get_unsigned_outputs_with_sighash_single_and_none(self):
     # Two inputs: SIGHASH_SINGLE and SIGHASH_NONE
     rawtx = '01000000027f71104801ceb380b2267c5a4f8ae619de4b91c20ea01376045d03f8cce05658010000006a47304402207ac4d4a61dcfd366de2815eeee613514d61013011ebb3bce495fe327d1fdd87c0220615099194fade423f2e5c7c6ce5d936cd60234f83375155f7a094bcba7641f1a032102d22e0c46e17c1c415eade7ce8d5ea5d3d118c801a5553c71420e77042060acf7ffffffff0000000000000000000000000000000000000000000000000000000000000000000000006b483045022100be36640aa006acc01e943b3b966d07978c87f0f3100e4d4c7779652af49754100220505ee957abd40c337d41c81fec53b52261b665352bf1ecbb82c773635dbc3912022102d22e0c46e17c1c415eade7ce8d5ea5d3d118c801a5553c71420e77042060acf7ffffffff02c09ee605000000001976a914f243c18ef3315b423b2ee33727e37b5fe318bf7c88ac00000000000000001976a914000000000000000000000000000000000000000088ac00000000'
     tx = Transaction.deserialize(x(rawtx))
     unsigned = get_unsigned_outputs(tx)
     self.assertEqual([1], unsigned)
示例#45
0
 def test_bitcoin_fields(self):
     tx = Transaction.deserialize(maza_raw_tx)
     self.assertEqual(bitcoin_fields, tx.fields)
     self.assertEqual(maza_raw_tx, tx.serialize())
示例#46
0
文件: tx.py 项目: Christewart/hashmal
 def set_tx(self, tx):
     """Reset the model to reflect tx."""
     self.beginResetModel()
     self.tx = Transaction.from_tx(tx)
     self.endResetModel()
示例#47
0
 def test_peercoin_fields(self):
     chainparams.set_tx_fields(peercoin_fields)
     tx = Transaction.deserialize(ppc_raw_tx)
     self.assertNotEqual(bitcoin_fields, tx.fields)
     self.assertIn(('Timestamp', b'<i', 4, 0), tx.fields)
     self.assertEqual(ppc_raw_tx, tx.serialize())
示例#48
0
 def coerce_hex_string(v):
     return Transaction.deserialize(x(v))
示例#49
0
 def test_chainparams_tx_serializer(self):
     chainparams.set_to_preset('Clams')
     tx = Transaction.deserialize(clams_raw_tx)
     self.assertEqual(clams_raw_tx, tx.serialize())
     tx2 = Transaction.deserialize(clams_v1_raw_tx)
     self.assertEqual(clams_v1_raw_tx, tx2.serialize())
示例#50
0
 def coerce_tx(v):
     return Transaction.from_tx(v)