Esempio n. 1
0
    def __init__(self, main_window, tree, parent=None):
        super(OutputsEditor, self).__init__(tree, parent)
        self.out_value = OutputAmountEdit()
        self.out_value.setToolTip('Output amount')
        self.out_value.setWhatsThis(
            'Use this field to specify the value of this output. Depending on your settings, the value may be in satoshis (no decimals), or coins (1 coin = 100000000 satoshis).'
        )
        self.script = ScriptEditor(main_window)
        self.script.setToolTip(
            'Script that will be put on the stack after the input that spends it.'
        )
        self.script.setWhatsThis(
            'Enter a script here. This script will be evaluated directly after the script of the input that spends it in the future. This script will have access to the values that are on the stack after the input script that spends it has executed.'
        )
        for i in [self.out_value, self.script]:
            i.setFont(monospace_font)

        self.mapper.addMapping(self.out_value, 0, 'satoshis')
        self.mapper.addMapping(self.script, 1, 'humanText')

        submit_button = QPushButton('Save')
        submit_button.setToolTip('Update input with the above data')
        submit_button.clicked.connect(self.do_submit)
        delete_button = QPushButton('Remove Output')
        delete_button.setToolTip('Remove this output from the transaction')
        delete_button.clicked.connect(self.do_delete)

        form = QFormLayout()
        form.setContentsMargins(0, 0, 0, 0)
        form.addRow('Amount: ', self.out_value)
        form.addRow('Output script: ', self.script)
        form.addRow(floated_buttons([delete_button, submit_button]))
        self.setLayout(form)
Esempio n. 2
0
class OutputsEditor(BaseEditor):
    def __init__(self, main_window, tree, parent=None):
        super(OutputsEditor, self).__init__(tree, parent)
        self.out_value = OutputAmountEdit()
        self.out_value.setToolTip('Output amount')
        self.out_value.setWhatsThis('Use this field to specify the value of this output. Depending on your settings, the value may be in satoshis (no decimals), or coins (1 coin = 100000000 satoshis).')
        self.script = ScriptEditor(main_window)
        self.script.setToolTip('Script that will be put on the stack after the input that spends it.')
        self.script.setWhatsThis('Enter a script here. This script will be evaluated directly after the script of the input that spends it in the future. This script will have access to the values that are on the stack after the input script that spends it has executed.')
        for i in [self.out_value, self.script]:
            i.setFont(monospace_font)

        self.mapper.addMapping(self.out_value, 0, 'satoshis')
        self.mapper.addMapping(self.script, 1, 'humanText')

        submit_button = QPushButton('Save')
        submit_button.setToolTip('Update input with the above data')
        submit_button.clicked.connect(self.do_submit)
        delete_button = QPushButton('Remove Output')
        delete_button.setToolTip('Remove this output from the transaction')
        delete_button.clicked.connect(self.do_delete)

        form = QFormLayout()
        form.setContentsMargins(0, 0, 0, 0)
        form.addRow('Amount: ', self.out_value)
        form.addRow('Output script: ', self.script)
        form.addRow(floated_buttons([delete_button, submit_button]))
        self.setLayout(form)
Esempio n. 3
0
class OutputsEditor(BaseEditor):
    def __init__(self, main_window, tree, parent=None):
        super(OutputsEditor, self).__init__(tree, parent)
        self.out_value = OutputAmountEdit()
        self.out_value.setToolTip("Output amount")
        self.script = ScriptEditor(main_window)
        self.script.setToolTip("Script that will be put on the stack after the input that spends it.")
        for i in [self.out_value, self.script]:
            i.setFont(monospace_font)

        self.mapper.addMapping(self.out_value, 0, "satoshis")
        self.mapper.addMapping(self.script, 1, "humanText")

        submit_button = QPushButton("Save")
        submit_button.setToolTip("Update input with the above data")
        submit_button.clicked.connect(self.do_submit)
        delete_button = QPushButton("Remove Output")
        delete_button.setToolTip("Remove this output from the transaction")
        delete_button.clicked.connect(self.do_delete)

        form = QFormLayout()
        form.setContentsMargins(0, 0, 0, 0)
        form.addRow("Amount: ", self.out_value)
        form.addRow("Output script: ", self.script)
        form.addRow(floated_buttons([delete_button, submit_button]))
        self.setLayout(form)
Esempio n. 4
0
    def __init__(self, main_window, tree, parent=None):
        super(OutputsEditor, self).__init__(tree, parent)
        self.out_value = OutputAmountEdit()
        self.out_value.setToolTip('Output amount')
        self.script = ScriptEditor(main_window)
        self.script.setToolTip('Script that will be put on the stack after the input that spends it.')
        for i in [self.out_value, self.script]:
            i.setFont(monospace_font)

        self.mapper.addMapping(self.out_value, 0, 'satoshis')
        self.mapper.addMapping(self.script, 1, 'humanText')

        submit_button = QPushButton('Save')
        submit_button.setToolTip('Update input with the above data')
        submit_button.clicked.connect(self.do_submit)
        delete_button = QPushButton('Remove Output')
        delete_button.setToolTip('Remove this output from the transaction')
        delete_button.clicked.connect(self.do_delete)

        form = QFormLayout()
        form.setContentsMargins(0, 0, 0, 0)
        form.addRow('Amount: ', self.out_value)
        form.addRow('Output script: ', self.script)
        form.addRow(floated_buttons([delete_button, submit_button]))
        self.setLayout(form)
Esempio n. 5
0
class InputsEditor(BaseEditor):
    def __init__(self, main_window, tree, parent=None):
        super(InputsEditor, self).__init__(tree, parent)
        self.prev_tx = QLineEdit()
        self.prev_tx.setToolTip('Transaction ID of the tx with the output being spent')
        self.prev_tx.setWhatsThis('Use this field to specify the transaction that contains the output you\'re spending.')

        self.prev_vout = AmountEdit()
        self.prev_vout.setToolTip('Output index of the previous transaction')
        self.prev_vout.setWhatsThis('Use this field to specify the output you are spending of the previous transaction.')

        self.script = ScriptEditor(main_window)
        self.script.setToolTip('Script that will be put on the stack before the previous output\'s script.')
        self.script.setWhatsThis('Enter a script here. This script will be evaluated directly before the script of the output you are spending. Any values that are pushed onto the stack when this script finishes its execution are present when the output script is evaluated afterward.')

        self.sequence = AmountEdit()
        self.sequence.setText('4294967295')
        self.sequence.setWhatsThis('Use this field to specify the sequence value. It\'s likely that you should leave this as its default (maximum) value.')
        maxify_input_sequence = QPushButton('Max')
        maxify_input_sequence.clicked.connect(lambda: self.sequence.setText('0xffffffff'))
        maxify_input_sequence.setWhatsThis('This button will set the sequence to its default value.')

        for i in [self.prev_tx, self.prev_vout, self.script, self.sequence]:
            i.setFont(monospace_font)

        self.mapper.addMapping(self.prev_tx, 0)
        self.mapper.addMapping(self.prev_vout, 1, 'amount')
        self.mapper.addMapping(self.script, 2, 'humanText')
        self.mapper.addMapping(self.sequence, 3, 'amount')

        delete_button = QPushButton('Remove Input')
        delete_button.setToolTip('Remove this input from the transaction')
        delete_button.clicked.connect(self.do_delete)
        submit_button = QPushButton('Save')
        submit_button.setToolTip('Update input with the above data')
        submit_button.clicked.connect(self.do_submit)

        form = QFormLayout()
        form.setContentsMargins(0, 0, 0, 0)
        form.addRow('Previous Transaction: ', self.prev_tx)
        form.addRow('Previous Tx Output: ', self.prev_vout)
        form.addRow('Input script: ', self.script)
        seq_desc = QLabel('Sequence is mostly deprecated.\nIf an input has a sequence that\'s not the maximum value, the transaction\'s locktime will apply.')
        seq_desc.setWordWrap(True)
        form.addRow(seq_desc)
        form.addRow('Sequence: ', HBox(self.sequence, maxify_input_sequence))
        form.addRow(floated_buttons([delete_button, submit_button]))

        self.setLayout(form)
Esempio n. 6
0
class InputsEditor(BaseEditor):
    def __init__(self, main_window, tree, parent=None):
        super(InputsEditor, self).__init__(tree, parent)
        self.prev_tx = QLineEdit()
        self.prev_tx.setToolTip("Transaction ID of the tx with the output being spent")

        self.prev_vout = AmountEdit()
        self.prev_vout.setToolTip("Output index of the previous transaction")

        self.script = ScriptEditor(main_window)
        self.script.setToolTip("Script that will be put on the stack before the previous output's script.")

        self.sequence = AmountEdit()
        self.sequence.setText("4294967295")
        maxify_input_sequence = QPushButton("Max")
        maxify_input_sequence.clicked.connect(lambda: self.sequence.setText("0xffffffff"))

        for i in [self.prev_tx, self.prev_vout, self.script, self.sequence]:
            i.setFont(monospace_font)

        self.mapper.addMapping(self.prev_tx, 0)
        self.mapper.addMapping(self.prev_vout, 1, "amount")
        self.mapper.addMapping(self.script, 2, "humanText")
        self.mapper.addMapping(self.sequence, 3, "amount")

        delete_button = QPushButton("Remove Input")
        delete_button.setToolTip("Remove this input from the transaction")
        delete_button.clicked.connect(self.do_delete)
        submit_button = QPushButton("Save")
        submit_button.setToolTip("Update input with the above data")
        submit_button.clicked.connect(self.do_submit)

        form = QFormLayout()
        form.setContentsMargins(0, 0, 0, 0)
        form.addRow("Previous Transaction: ", self.prev_tx)
        form.addRow("Previous Tx Output: ", self.prev_vout)
        form.addRow("Input script: ", self.script)
        seq_desc = QLabel(
            "Sequence is mostly deprecated.\nIf an input has a sequence that's not the maximum value, the transaction's locktime will apply."
        )
        seq_desc.setWordWrap(True)
        form.addRow(seq_desc)
        form.addRow("Sequence: ", HBox(self.sequence, maxify_input_sequence))
        form.addRow(floated_buttons([delete_button, submit_button]))

        self.setLayout(form)
Esempio n. 7
0
class InputsEditor(BaseEditor):
    def __init__(self, main_window, tree, parent=None):
        super(InputsEditor, self).__init__(tree, parent)
        self.prev_tx = QLineEdit()
        self.prev_tx.setToolTip('Transaction ID of the tx with the output being spent')

        self.prev_vout = AmountEdit()
        self.prev_vout.setToolTip('Output index of the previous transaction')

        self.script = ScriptEditor(main_window)
        self.script.setToolTip('Script that will be put on the stack before the previous output\'s script.')

        self.sequence = AmountEdit()
        self.sequence.setText('4294967295')
        maxify_input_sequence = QPushButton('Max')
        maxify_input_sequence.clicked.connect(lambda: self.sequence.setText('0xffffffff'))

        for i in [self.prev_tx, self.prev_vout, self.script, self.sequence]:
            i.setFont(monospace_font)

        self.mapper.addMapping(self.prev_tx, 0)
        self.mapper.addMapping(self.prev_vout, 1, 'amount')
        self.mapper.addMapping(self.script, 2, 'humanText')
        self.mapper.addMapping(self.sequence, 3, 'amount')

        delete_button = QPushButton('Remove Input')
        delete_button.setToolTip('Remove this input from the transaction')
        delete_button.clicked.connect(self.do_delete)
        submit_button = QPushButton('Save')
        submit_button.setToolTip('Update input with the above data')
        submit_button.clicked.connect(self.do_submit)

        form = QFormLayout()
        form.setContentsMargins(0, 0, 0, 0)
        form.addRow('Previous Transaction: ', self.prev_tx)
        form.addRow('Previous Tx Output: ', self.prev_vout)
        form.addRow('Input script: ', self.script)
        seq_desc = QLabel('Sequence is mostly deprecated.\nIf an input has a sequence that\'s not the maximum value, the transaction\'s locktime will apply.')
        seq_desc.setWordWrap(True)
        form.addRow(seq_desc)
        form.addRow('Sequence: ', HBox(self.sequence, maxify_input_sequence))
        form.addRow(floated_buttons([delete_button, submit_button]))

        self.setLayout(form)
Esempio n. 8
0
    def __init__(self, dock, parent=None):
        super(SigHashWidget, self).__init__(parent)
        self.dock = dock
        self.model = SigHashModel()

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.model)

        self.utxo_script = ScriptEditor(self.dock.handler.gui)
        self.utxo_script.setToolTip('Script from the unspent output')
        self.utxo_script.setWhatsThis(
            'Enter the output script from the unspent output you are spending here.'
        )
        self.utxo_script.setFixedHeight(42)
        self.inIdx = QSpinBox()
        self.inIdx.setRange(0, 0)
        self.inIdx.setToolTip('Input to sign')
        self.inIdx.setWhatsThis(
            'This specifies the input that will be signed.')
        self.sighash_type = QComboBox()
        self.sighash_type.setToolTip('Signature hash type')
        self.sighash_type.setWhatsThis(
            'Use this to specify the signature hash flag you want to use. The flags have different effects and are explained in the box to the right.'
        )
        self.sighash_type.addItems(
            ['SIGHASH_ALL', 'SIGHASH_NONE', 'SIGHASH_SINGLE'])
        self.anyone_can_pay = QCheckBox('SIGHASH_ANYONECANPAY')
        self.anyone_can_pay.setWhatsThis(
            'Use this to add the ANYONECANPAY flag to your signature hash type. Its effect is explained in the box to the right.'
        )
        self.sighash_name = QLineEdit()
        self.sighash_name.setToolTip('Signature hash name')
        self.sighash_name.setWhatsThis(
            'The full name of your current signature hash type is shown here.')
        self.sighash_explanation = QTextEdit()
        self.sighash_explanation.setToolTip('Signature hash explanation')
        self.sighash_explanation.setWhatsThis(
            'A description of your current signature hash type is shown here.')
        for i in [self.sighash_name, self.sighash_explanation]:
            i.setReadOnly(True)

        self.mapper.addMapping(self.utxo_script, 0, 'humanText')
        self.mapper.addMapping(self.inIdx, 2)
        self.mapper.addMapping(self.sighash_type, 3)
        self.mapper.addMapping(self.anyone_can_pay, 4)
        self.mapper.addMapping(self.sighash_name, SigHashModel.SigHashName)
        self.mapper.addMapping(self.sighash_explanation,
                               SigHashModel.SigHashExplanation)

        self.privkey_edit = QLineEdit()
        self.privkey_edit.setWhatsThis(
            'Use this to enter a private key with which to sign the transaction.'
        )
        self.privkey_edit.setPlaceholderText('Enter a private key')
        self.sign_button = QPushButton('Sign')
        self.sign_button.setToolTip('Sign transaction')
        self.sign_button.setWhatsThis(
            'Clicking this button will attempt to sign the transaction with your private key.'
        )
        self.sign_button.clicked.connect(self.sign_transaction)
        self.verify_script = QCheckBox('Verify script')
        self.verify_script.setToolTip('Verify input script')
        self.verify_script.setWhatsThis(
            'If this is checked, Hashmal will attempt to verify the completed script.'
        )
        signing_form = QFormLayout()
        privkey_hbox = QHBoxLayout()
        privkey_hbox.addWidget(self.privkey_edit, stretch=1)
        privkey_hbox.addWidget(self.sign_button)
        privkey_hbox.addWidget(self.verify_script)
        self.result_edit = QLineEdit()
        self.result_edit.setReadOnly(True)
        self.result_edit.setPlaceholderText('Result of signing')
        self.result_edit.setWhatsThis(
            'The result of signing the transaction will be shown here.')
        signing_form.addRow('Private Key:', privkey_hbox)
        signing_form.addRow('Result:', self.result_edit)

        tx_form = QFormLayout()
        tx_form.addRow('Unspent Output Script:', self.utxo_script)
        tx_form.addRow('Input To Sign:', self.inIdx)

        sighash_controls = QFormLayout()
        sighash_controls.addRow('SigHash flag:', self.sighash_type)
        sighash_controls.addRow(self.anyone_can_pay)
        sighash_info = QVBoxLayout()
        sighash_info.addWidget(self.sighash_name)
        sighash_info.addWidget(self.sighash_explanation)
        sighash_layout = QHBoxLayout()
        sighash_layout.addLayout(sighash_controls)
        sighash_layout.addLayout(sighash_info)

        vbox = QVBoxLayout()
        vbox.addLayout(signing_form)
        vbox.addWidget(Separator())
        vbox.addLayout(tx_form)
        vbox.addWidget(Separator())
        vbox.addLayout(sighash_layout)
        self.setLayout(vbox)

        self.mapper.toFirst()
Esempio n. 9
0
class SigHashWidget(QWidget):
    """Model and view of a transaction's signature hash."""
    def __init__(self, dock, parent=None):
        super(SigHashWidget, self).__init__(parent)
        self.dock = dock
        self.model = SigHashModel()

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.model)

        self.utxo_script = ScriptEditor(self.dock.handler.gui)
        self.utxo_script.setToolTip('Script from the unspent output')
        self.utxo_script.setWhatsThis(
            'Enter the output script from the unspent output you are spending here.'
        )
        self.utxo_script.setFixedHeight(42)
        self.inIdx = QSpinBox()
        self.inIdx.setRange(0, 0)
        self.inIdx.setToolTip('Input to sign')
        self.inIdx.setWhatsThis(
            'This specifies the input that will be signed.')
        self.sighash_type = QComboBox()
        self.sighash_type.setToolTip('Signature hash type')
        self.sighash_type.setWhatsThis(
            'Use this to specify the signature hash flag you want to use. The flags have different effects and are explained in the box to the right.'
        )
        self.sighash_type.addItems(
            ['SIGHASH_ALL', 'SIGHASH_NONE', 'SIGHASH_SINGLE'])
        self.anyone_can_pay = QCheckBox('SIGHASH_ANYONECANPAY')
        self.anyone_can_pay.setWhatsThis(
            'Use this to add the ANYONECANPAY flag to your signature hash type. Its effect is explained in the box to the right.'
        )
        self.sighash_name = QLineEdit()
        self.sighash_name.setToolTip('Signature hash name')
        self.sighash_name.setWhatsThis(
            'The full name of your current signature hash type is shown here.')
        self.sighash_explanation = QTextEdit()
        self.sighash_explanation.setToolTip('Signature hash explanation')
        self.sighash_explanation.setWhatsThis(
            'A description of your current signature hash type is shown here.')
        for i in [self.sighash_name, self.sighash_explanation]:
            i.setReadOnly(True)

        self.mapper.addMapping(self.utxo_script, 0, 'humanText')
        self.mapper.addMapping(self.inIdx, 2)
        self.mapper.addMapping(self.sighash_type, 3)
        self.mapper.addMapping(self.anyone_can_pay, 4)
        self.mapper.addMapping(self.sighash_name, SigHashModel.SigHashName)
        self.mapper.addMapping(self.sighash_explanation,
                               SigHashModel.SigHashExplanation)

        self.privkey_edit = QLineEdit()
        self.privkey_edit.setWhatsThis(
            'Use this to enter a private key with which to sign the transaction.'
        )
        self.privkey_edit.setPlaceholderText('Enter a private key')
        self.sign_button = QPushButton('Sign')
        self.sign_button.setToolTip('Sign transaction')
        self.sign_button.setWhatsThis(
            'Clicking this button will attempt to sign the transaction with your private key.'
        )
        self.sign_button.clicked.connect(self.sign_transaction)
        self.verify_script = QCheckBox('Verify script')
        self.verify_script.setToolTip('Verify input script')
        self.verify_script.setWhatsThis(
            'If this is checked, Hashmal will attempt to verify the completed script.'
        )
        signing_form = QFormLayout()
        privkey_hbox = QHBoxLayout()
        privkey_hbox.addWidget(self.privkey_edit, stretch=1)
        privkey_hbox.addWidget(self.sign_button)
        privkey_hbox.addWidget(self.verify_script)
        self.result_edit = QLineEdit()
        self.result_edit.setReadOnly(True)
        self.result_edit.setPlaceholderText('Result of signing')
        self.result_edit.setWhatsThis(
            'The result of signing the transaction will be shown here.')
        signing_form.addRow('Private Key:', privkey_hbox)
        signing_form.addRow('Result:', self.result_edit)

        tx_form = QFormLayout()
        tx_form.addRow('Unspent Output Script:', self.utxo_script)
        tx_form.addRow('Input To Sign:', self.inIdx)

        sighash_controls = QFormLayout()
        sighash_controls.addRow('SigHash flag:', self.sighash_type)
        sighash_controls.addRow(self.anyone_can_pay)
        sighash_info = QVBoxLayout()
        sighash_info.addWidget(self.sighash_name)
        sighash_info.addWidget(self.sighash_explanation)
        sighash_layout = QHBoxLayout()
        sighash_layout.addLayout(sighash_controls)
        sighash_layout.addLayout(sighash_info)

        vbox = QVBoxLayout()
        vbox.addLayout(signing_form)
        vbox.addWidget(Separator())
        vbox.addLayout(tx_form)
        vbox.addWidget(Separator())
        vbox.addLayout(sighash_layout)
        self.setLayout(vbox)

        self.mapper.toFirst()

    def set_tx(self, tx):
        self.inIdx.setRange(0, len(tx.vin) - 1)
        self.model.set_tx(tx)
        self.mapper.toFirst()

    def clear(self):
        self.result_edit.clear()
        self.result_edit.setProperty('hasError', False)
        self.style().polish(self.result_edit)
        self.model.clear()

    def set_result_message(self, text, error=False):
        self.result_edit.setText(text)
        self.result_edit.setProperty('hasError', error)
        self.style().polish(self.result_edit)
        if error:
            self.dock.error(text)
        else:
            self.dock.info(text)

    def sign_transaction(self):
        """Sign the transaction."""
        script, txTo, inIdx, hash_type = self.model.get_fields()
        if inIdx >= len(txTo.vin):
            self.set_result_message('Nonexistent input specified for signing.',
                                    error=True)
            return
        if not script:
            self.set_result_message('Invalid output script.', error=True)
            return
        privkey = self.get_private_key()
        if not privkey:
            self.set_result_message('Could not parse private key.', error=True)
            return
        sig_hash = chainparams.signature_hash(script, txTo, inIdx, hash_type)

        sig = privkey.sign(sig_hash)
        hash_type_hex = format_hex_string(hex(hash_type),
                                          with_prefix=False).decode('hex')
        sig = sig + hash_type_hex
        txTo.vin[inIdx].scriptSig = Script([sig, privkey.pub])

        if self.verify_script.isChecked():
            # Try verify
            try:
                VerifyScript(txTo.vin[inIdx].scriptSig, script, txTo, inIdx,
                             (SCRIPT_VERIFY_P2SH, ))
            except Exception as e:
                self.set_result_message('Error when verifying: %s' % str(e),
                                        error=True)
                return

        self.dock.deserialize_raw(b2x(txTo.serialize()))
        # Deserializing a tx clears the model, so re-populate.
        self.model.set_fields(script=script.get_human(),
                              inIdx=inIdx,
                              hashType=hash_type)
        self.set_result_message(
            'Successfully set scriptSig for input %d (SigHash type: %s).' %
            (inIdx, sig_hash_name(hash_type)))

    def get_private_key(self):
        """Attempt to parse the private key that was input."""
        txt = str(self.privkey_edit.text())
        privkey = None
        if is_hex(txt):
            txt = format_hex_string(txt, with_prefix=False)

        try:
            privkey = CBitcoinSecret.from_secret_bytes(x(txt))
        except Exception:
            pass

        return privkey
Esempio n. 10
0
    def __init__(self, main_window, tree, parent=None):
        super(InputsEditor, self).__init__(tree, parent)
        self.prev_tx = QLineEdit()
        self.prev_tx.setToolTip(
            'Transaction ID of the tx with the output being spent')
        self.prev_tx.setWhatsThis(
            'Use this field to specify the transaction that contains the output you\'re spending.'
        )

        self.prev_vout = AmountEdit()
        self.prev_vout.setToolTip('Output index of the previous transaction')
        self.prev_vout.setWhatsThis(
            'Use this field to specify the output you are spending of the previous transaction.'
        )

        self.script = ScriptEditor(main_window)
        self.script.setToolTip(
            'Script that will be put on the stack before the previous output\'s script.'
        )
        self.script.setWhatsThis(
            'Enter a script here. This script will be evaluated directly before the script of the output you are spending. Any values that are pushed onto the stack when this script finishes its execution are present when the output script is evaluated afterward.'
        )

        self.sequence = AmountEdit()
        self.sequence.setText('4294967295')
        self.sequence.setWhatsThis(
            'Use this field to specify the sequence value. It\'s likely that you should leave this as its default (maximum) value.'
        )
        maxify_input_sequence = QPushButton('Max')
        maxify_input_sequence.clicked.connect(
            lambda: self.sequence.setText('0xffffffff'))
        maxify_input_sequence.setWhatsThis(
            'This button will set the sequence to its default value.')

        for i in [self.prev_tx, self.prev_vout, self.script, self.sequence]:
            i.setFont(monospace_font)

        self.mapper.addMapping(self.prev_tx, 0)
        self.mapper.addMapping(self.prev_vout, 1, 'amount')
        self.mapper.addMapping(self.script, 2, 'humanText')
        self.mapper.addMapping(self.sequence, 3, 'amount')

        delete_button = QPushButton('Remove Input')
        delete_button.setToolTip('Remove this input from the transaction')
        delete_button.clicked.connect(self.do_delete)
        submit_button = QPushButton('Save')
        submit_button.setToolTip('Update input with the above data')
        submit_button.clicked.connect(self.do_submit)

        form = QFormLayout()
        form.setContentsMargins(0, 0, 0, 0)
        form.addRow('Previous Transaction: ', self.prev_tx)
        form.addRow('Previous Tx Output: ', self.prev_vout)
        form.addRow('Input script: ', self.script)
        seq_desc = QLabel(
            'Sequence is mostly deprecated.\nIf an input has a sequence that\'s not the maximum value, the transaction\'s locktime will apply.'
        )
        seq_desc.setWordWrap(True)
        form.addRow(seq_desc)
        form.addRow('Sequence: ', HBox(self.sequence, maxify_input_sequence))
        form.addRow(floated_buttons([delete_button, submit_button]))

        self.setLayout(form)
Esempio n. 11
0
    def __init__(self, dock, parent=None):
        super(SigHashWidget, self).__init__(parent)
        self.dock = dock
        self.model = SigHashModel()

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.model)

        self.utxo_script = ScriptEditor(self.dock.handler.gui)
        self.utxo_script.setToolTip('Script from the unspent output')
        self.utxo_script.setWhatsThis('Enter the output script from the unspent output you are spending here.')
        self.utxo_script.setFixedHeight(42)
        self.inIdx = QSpinBox()
        self.inIdx.setRange(0, 0)
        self.inIdx.setToolTip('Input to sign')
        self.inIdx.setWhatsThis('This specifies the input that will be signed.')
        self.sighash_type = QComboBox()
        self.sighash_type.setToolTip('Signature hash type')
        self.sighash_type.setWhatsThis('Use this to specify the signature hash flag you want to use. The flags have different effects and are explained in the box to the right.')
        self.sighash_type.addItems(['SIGHASH_ALL', 'SIGHASH_NONE', 'SIGHASH_SINGLE'])
        self.anyone_can_pay = QCheckBox('SIGHASH_ANYONECANPAY')
        self.anyone_can_pay.setWhatsThis('Use this to add the ANYONECANPAY flag to your signature hash type. Its effect is explained in the box to the right.')
        self.sighash_name = QLineEdit()
        self.sighash_name.setToolTip('Signature hash name')
        self.sighash_name.setWhatsThis('The full name of your current signature hash type is shown here.')
        self.sighash_explanation = QTextEdit()
        self.sighash_explanation.setToolTip('Signature hash explanation')
        self.sighash_explanation.setWhatsThis('A description of your current signature hash type is shown here.')
        for i in [self.sighash_name, self.sighash_explanation]:
            i.setReadOnly(True)

        self.mapper.addMapping(self.utxo_script, 0, 'humanText')
        self.mapper.addMapping(self.inIdx, 2)
        self.mapper.addMapping(self.sighash_type, 3)
        self.mapper.addMapping(self.anyone_can_pay, 4)
        self.mapper.addMapping(self.sighash_name, SigHashModel.SigHashName)
        self.mapper.addMapping(self.sighash_explanation, SigHashModel.SigHashExplanation)

        self.privkey_edit = QLineEdit()
        self.privkey_edit.setWhatsThis('Use this to enter a private key with which to sign the transaction.')
        self.privkey_edit.setPlaceholderText('Enter a private key')
        self.sign_button = QPushButton('Sign')
        self.sign_button.setToolTip('Sign transaction')
        self.sign_button.setWhatsThis('Clicking this button will attempt to sign the transaction with your private key.')
        self.sign_button.clicked.connect(self.sign_transaction)
        self.verify_script = QCheckBox('Verify script')
        self.verify_script.setToolTip('Verify input script')
        self.verify_script.setWhatsThis('If this is checked, Hashmal will attempt to verify the completed script.')
        signing_form = QFormLayout()
        privkey_hbox = QHBoxLayout()
        privkey_hbox.addWidget(self.privkey_edit, stretch=1)
        privkey_hbox.addWidget(self.sign_button)
        privkey_hbox.addWidget(self.verify_script)
        self.result_edit = QLineEdit()
        self.result_edit.setReadOnly(True)
        self.result_edit.setPlaceholderText('Result of signing')
        self.result_edit.setWhatsThis('The result of signing the transaction will be shown here.')
        signing_form.addRow('Private Key:', privkey_hbox)
        signing_form.addRow('Result:', self.result_edit)

        tx_form = QFormLayout()
        tx_form.addRow('Unspent Output Script:', self.utxo_script)
        tx_form.addRow('Input To Sign:', self.inIdx)

        sighash_controls = QFormLayout()
        sighash_controls.addRow('SigHash flag:', self.sighash_type)
        sighash_controls.addRow(self.anyone_can_pay)
        sighash_info = QVBoxLayout()
        sighash_info.addWidget(self.sighash_name)
        sighash_info.addWidget(self.sighash_explanation)
        sighash_layout = QHBoxLayout()
        sighash_layout.addLayout(sighash_controls)
        sighash_layout.addLayout(sighash_info)

        vbox = QVBoxLayout()
        vbox.addLayout(signing_form)
        vbox.addWidget(Separator())
        vbox.addLayout(tx_form)
        vbox.addWidget(Separator())
        vbox.addLayout(sighash_layout)
        self.setLayout(vbox)

        self.mapper.toFirst()
Esempio n. 12
0
class SigHashWidget(QWidget):
    """Model and view of a transaction's signature hash."""
    def __init__(self, dock, parent=None):
        super(SigHashWidget, self).__init__(parent)
        self.dock = dock
        self.model = SigHashModel()

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.model)

        self.utxo_script = ScriptEditor(self.dock.handler.gui)
        self.utxo_script.setToolTip('Script from the unspent output')
        self.utxo_script.setWhatsThis('Enter the output script from the unspent output you are spending here.')
        self.utxo_script.setFixedHeight(42)
        self.inIdx = QSpinBox()
        self.inIdx.setRange(0, 0)
        self.inIdx.setToolTip('Input to sign')
        self.inIdx.setWhatsThis('This specifies the input that will be signed.')
        self.sighash_type = QComboBox()
        self.sighash_type.setToolTip('Signature hash type')
        self.sighash_type.setWhatsThis('Use this to specify the signature hash flag you want to use. The flags have different effects and are explained in the box to the right.')
        self.sighash_type.addItems(['SIGHASH_ALL', 'SIGHASH_NONE', 'SIGHASH_SINGLE'])
        self.anyone_can_pay = QCheckBox('SIGHASH_ANYONECANPAY')
        self.anyone_can_pay.setWhatsThis('Use this to add the ANYONECANPAY flag to your signature hash type. Its effect is explained in the box to the right.')
        self.sighash_name = QLineEdit()
        self.sighash_name.setToolTip('Signature hash name')
        self.sighash_name.setWhatsThis('The full name of your current signature hash type is shown here.')
        self.sighash_explanation = QTextEdit()
        self.sighash_explanation.setToolTip('Signature hash explanation')
        self.sighash_explanation.setWhatsThis('A description of your current signature hash type is shown here.')
        for i in [self.sighash_name, self.sighash_explanation]:
            i.setReadOnly(True)

        self.mapper.addMapping(self.utxo_script, 0, 'humanText')
        self.mapper.addMapping(self.inIdx, 2)
        self.mapper.addMapping(self.sighash_type, 3)
        self.mapper.addMapping(self.anyone_can_pay, 4)
        self.mapper.addMapping(self.sighash_name, SigHashModel.SigHashName)
        self.mapper.addMapping(self.sighash_explanation, SigHashModel.SigHashExplanation)

        self.privkey_edit = QLineEdit()
        self.privkey_edit.setWhatsThis('Use this to enter a private key with which to sign the transaction.')
        self.privkey_edit.setPlaceholderText('Enter a private key')
        self.sign_button = QPushButton('Sign')
        self.sign_button.setToolTip('Sign transaction')
        self.sign_button.setWhatsThis('Clicking this button will attempt to sign the transaction with your private key.')
        self.sign_button.clicked.connect(self.sign_transaction)
        self.verify_script = QCheckBox('Verify script')
        self.verify_script.setToolTip('Verify input script')
        self.verify_script.setWhatsThis('If this is checked, Hashmal will attempt to verify the completed script.')
        signing_form = QFormLayout()
        privkey_hbox = QHBoxLayout()
        privkey_hbox.addWidget(self.privkey_edit, stretch=1)
        privkey_hbox.addWidget(self.sign_button)
        privkey_hbox.addWidget(self.verify_script)
        self.result_edit = QLineEdit()
        self.result_edit.setReadOnly(True)
        self.result_edit.setPlaceholderText('Result of signing')
        self.result_edit.setWhatsThis('The result of signing the transaction will be shown here.')
        signing_form.addRow('Private Key:', privkey_hbox)
        signing_form.addRow('Result:', self.result_edit)

        tx_form = QFormLayout()
        tx_form.addRow('Unspent Output Script:', self.utxo_script)
        tx_form.addRow('Input To Sign:', self.inIdx)

        sighash_controls = QFormLayout()
        sighash_controls.addRow('SigHash flag:', self.sighash_type)
        sighash_controls.addRow(self.anyone_can_pay)
        sighash_info = QVBoxLayout()
        sighash_info.addWidget(self.sighash_name)
        sighash_info.addWidget(self.sighash_explanation)
        sighash_layout = QHBoxLayout()
        sighash_layout.addLayout(sighash_controls)
        sighash_layout.addLayout(sighash_info)

        vbox = QVBoxLayout()
        vbox.addLayout(signing_form)
        vbox.addWidget(Separator())
        vbox.addLayout(tx_form)
        vbox.addWidget(Separator())
        vbox.addLayout(sighash_layout)
        self.setLayout(vbox)

        self.mapper.toFirst()

    def set_tx(self, tx):
        self.inIdx.setRange(0, len(tx.vin) - 1)
        self.model.set_tx(tx)
        self.mapper.toFirst()

    def clear(self):
        self.result_edit.clear()
        self.result_edit.setProperty('hasError', False)
        self.style().polish(self.result_edit)
        self.model.clear()

    def set_result_message(self, text, error=False):
        self.result_edit.setText(text)
        self.result_edit.setProperty('hasError', error)
        self.style().polish(self.result_edit)
        if error:
            self.dock.error(text)
        else:
            self.dock.info(text)

    def sign_transaction(self):
        """Sign the transaction."""
        script, txTo, inIdx, hash_type = self.model.get_fields()
        if inIdx >= len(txTo.vin):
            self.set_result_message('Nonexistent input specified for signing.', error=True)
            return
        if not script:
            self.set_result_message('Invalid output script.', error=True)
            return
        privkey = self.get_private_key()
        if not privkey:
            self.set_result_message('Could not parse private key.', error=True)
            return
        sig_hash = chainparams.signature_hash(script, txTo, inIdx, hash_type)

        sig = privkey.sign(sig_hash)
        hash_type_hex = format_hex_string(hex(hash_type), with_prefix=False).decode('hex')
        sig = sig + hash_type_hex
        txTo.vin[inIdx].scriptSig = Script([sig, privkey.pub])

        if self.verify_script.isChecked():
            # Try verify
            try:
                VerifyScript(txTo.vin[inIdx].scriptSig, script, txTo, inIdx, (SCRIPT_VERIFY_P2SH,))
            except Exception as e:
                self.set_result_message('Error when verifying: %s' % str(e), error=True)
                return

        self.dock.deserialize_raw(b2x(txTo.serialize()))
        # Deserializing a tx clears the model, so re-populate.
        self.model.set_fields(script=script.get_human(), inIdx=inIdx, hashType=hash_type)
        self.set_result_message('Successfully set scriptSig for input %d (SigHash type: %s).' % (inIdx, sig_hash_name(hash_type)))

    def get_private_key(self):
        """Attempt to parse the private key that was input."""
        txt = str(self.privkey_edit.text())
        privkey = None
        if is_hex(txt):
            txt = format_hex_string(txt, with_prefix=False)

        try:
            privkey = CBitcoinSecret.from_secret_bytes(x(txt))
        except Exception:
            pass

        return privkey