예제 #1
0
    def create_verify_tab(self):
        form = QFormLayout()
        form.setRowWrapPolicy(QFormLayout.WrapLongRows)

        self.inputs_box = QSpinBox()

        self.verify_button = QPushButton('Verify')
        self.verify_button.clicked.connect(self.verify_input)

        self.verify_all_button = QPushButton('Verify All')
        self.verify_all_button.clicked.connect(self.verify_inputs)

        self.result_edit = QLineEdit()
        self.result_edit.setReadOnly(True)

        self.inputs_table = InputStatusTable()

        form.addRow('Verify Input:',
                    floated_buttons([self.inputs_box, self.verify_button]))
        form.addRow(floated_buttons([self.verify_all_button]))
        form.addRow('Result:', self.result_edit)
        form.addRow(self.inputs_table)

        w = QWidget()
        w.setLayout(form)
        return w
예제 #2
0
    def create_verify_tab(self):
        form = QFormLayout()
        form.setRowWrapPolicy(QFormLayout.WrapLongRows)

        self.inputs_box = QSpinBox()
        self.inputs_box.setToolTip('Input to verify')

        self.verify_button = QPushButton('Verify')
        self.verify_button.clicked.connect(self.verify_input)
        self.verify_button.setToolTip('Verify an input')
        self.verify_button.setWhatsThis('This button will attempt to verify an input.\n\nIf no plugin is available to retrieve blockchain data, such as the "Blockchain" or "Wallet RPC" plugins, this will not function. The plugin used to retrieve blockchain data can be changed in the Settings dialog.')

        self.verify_all_button = QPushButton('Verify All')
        self.verify_all_button.clicked.connect(self.verify_inputs)
        self.verify_all_button.setToolTip('Verify all inputs')
        self.verify_all_button.setWhatsThis('This button will attempt to verify all inputs.\n\nIf no plugin is available to retrieve blockchain data, such as the "Blockchain" or "Wallet RPC" plugins, this will not function. The plugin used to retrieve blockchain data can be changed in the Settings dialog.')

        self.result_edit = QLineEdit()
        self.result_edit.setToolTip('Verification result')
        self.result_edit.setWhatsThis('The result of verifying an input is shown here.')
        self.result_edit.setReadOnly(True)

        self.inputs_table = InputStatusTable()
        self.inputs_table.setToolTip('Verification results')
        self.inputs_table.setWhatsThis('This table displays which inputs you have verified for the transaction being analyzed.')

        form.addRow('Verify Input:', floated_buttons([self.inputs_box, self.verify_button]))
        form.addRow(floated_buttons([self.verify_all_button]))
        form.addRow('Result:', self.result_edit)
        form.addRow(self.inputs_table)

        w = QWidget()
        w.setLayout(form)
        return w
예제 #3
0
    def create_verify_tab(self):
        form = QFormLayout()
        form.setRowWrapPolicy(QFormLayout.WrapLongRows)

        self.inputs_box = QSpinBox()

        self.verify_button = QPushButton('Verify')
        self.verify_button.clicked.connect(self.verify_input)

        self.verify_all_button = QPushButton('Verify All')
        self.verify_all_button.clicked.connect(self.verify_inputs)

        self.result_edit = QLineEdit()
        self.result_edit.setReadOnly(True)

        self.inputs_table = InputStatusTable()

        form.addRow('Verify Input:', floated_buttons([self.inputs_box, self.verify_button]))
        form.addRow(floated_buttons([self.verify_all_button]))
        form.addRow('Result:', self.result_edit)
        form.addRow(self.inputs_table)

        w = QWidget()
        w.setLayout(form)
        return w
예제 #4
0
    def create_layout(self):
        self.payload_edit = QPlainTextEdit()
        self.handler.substitute_variables(self.payload_edit)
        self.payload_edit.setToolTip('Hex data')
        self.payload_edit.setWhatsThis('Enter hex data that you want to base58-encode here.')
        self.encoded_edit = QPlainTextEdit()
        self.handler.substitute_variables(self.encoded_edit)
        self.encoded_edit.setToolTip('Base58 data')
        self.encoded_edit.setWhatsThis('Enter base58 data that you want to decode here.')

        for i in [self.payload_edit, self.encoded_edit]:
            i.setTabChangesFocus(True)

        self.encode_button = QPushButton('Encode')
        self.encode_button.setWhatsThis('Click this to base58-encode the above data.')
        self.encode_button.clicked.connect(self.encode_data)
        self.decode_button = QPushButton('Decode')
        self.decode_button.setWhatsThis('Click this to decode the above base58 data.')
        self.decode_button.clicked.connect(self.decode_data)

        encode_vbox = QVBoxLayout()
        encode_vbox.addWidget(self.payload_edit)
        encode_vbox.addLayout(floated_buttons([self.encode_button]))

        decode_vbox = QVBoxLayout()
        decode_vbox.addWidget(self.encoded_edit)
        decode_vbox.addLayout(floated_buttons([self.decode_button]))

        vbox = QVBoxLayout()
        vbox.addLayout(encode_vbox)
        vbox.addWidget(Separator())
        vbox.addLayout(decode_vbox)
        vbox.addStretch(1)

        return vbox
예제 #5
0
    def create_main_tab(self):
        self.execution_widget = ScriptExecutionWidget(self.execution)
        # For variable substitution
        self.execution_widget.model.plugin_handler = self.handler

        self.execution_delegate = ScriptExecutionDelegate()
        self.execution_widget.view.setItemDelegate(self.execution_delegate)

        # Raw script input.
        self.tx_script = QPlainTextEdit()
        self.tx_script.setWhatsThis('Enter a raw script here to evaluate it.')
        self.tx_script.setFont(monospace_font)
        self.tx_script.setTabChangesFocus(True)

        self.clear_button = QPushButton('Clear')
        self.clear_button.setToolTip('Clear the current script.')
        self.clear_button.clicked.connect(self.reset)
        self.do_button = QPushButton('&Evaluate')
        self.do_button.setToolTip('Evaluate the entire script.')
        self.do_button.clicked.connect(self.do_evaluate)
        btn_hbox = floated_buttons([self.clear_button, self.do_button], left=True)

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel('Script:'))
        vbox.addWidget(self.tx_script)
        vbox.addLayout(btn_hbox)
        vbox.addWidget(self.execution_widget, stretch=1)

        self.next_button = QPushButton('Next')
        self.next_button.setToolTip('Step forward in script execution.')
        self.next_button.clicked.connect(self.execution_widget.select_next)
        self.prev_button = QPushButton('Previous')
        self.prev_button.setToolTip('Step backward in script execution.')
        self.prev_button.clicked.connect(self.execution_widget.select_prev)

        controls_hbox = floated_buttons([self.prev_button, self.next_button], left=True)
        vbox.addLayout(controls_hbox)

        self.script_passed = ReadOnlyCheckBox('Passed')
        self.script_passed.setToolTip('Whether the script passed')
        self.script_passed.setWhatsThis('This box is checked if the script finished with a nonzero top stack value.')
        self.script_verified = ReadOnlyCheckBox('Verified')
        self.script_verified.setToolTip('Whether the script was verified with an input script')
        self.script_verified.setWhatsThis('This box is checked if the script was verified with a transaction\'s input script.')
        pass_hbox = HBox(QLabel('Script: '), self.script_passed, self.script_verified)
        pass_hbox.addStretch(1)
        vbox.addLayout(pass_hbox)

        w = QWidget()
        w.setLayout(vbox)
        return w
예제 #6
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)
예제 #7
0
    def create_outputs_tab(self):
        form = QFormLayout()
        self.outputs_tree = OutputsTree()
        self.outputs_editor = OutputsEditor(self.handler.gui, self.outputs_tree)
        self.outputs_editor.setEnabled(False)

        def update_enabled_widgets():
            num_outputs = len(self.outputs_tree.get_outputs())
            self.outputs_editor.setEnabled(num_outputs > 0)

        def add_output():
            new_output = CMutableTxOut(0)
            self.outputs_tree.add_output(new_output)

            update_enabled_widgets()
            if len(self.outputs_tree.get_outputs()) > 0:
                self.outputs_tree.view.selectRow(self.outputs_tree.model.rowCount() - 1)

        update_enabled_widgets()

        add_output_button = QPushButton('New output')
        add_output_button.setToolTip('Add a new output')
        add_output_button.clicked.connect(add_output)

        form.addRow(self.outputs_tree)
        form.addRow(Separator())

        form.addRow(self.outputs_editor)

        form.addRow(Separator())
        form.addRow(floated_buttons([add_output_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #8
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)
예제 #9
0
    def create_explorer_tab(self):
        form = QFormLayout()

        set_default_button = QPushButton('Save as default')
        set_default_button.setToolTip('Save this block explorer as default')

        def set_default():
            chain = str(chain_combo.currentText())
            txt = str(explorer_combo.currentText())
            self.config.set_option('block_explorer', ':'.join([chain, txt]))
        set_default_button.clicked.connect(set_default)


        self.chain_combo = chain_combo = QComboBox()
        chain_combo.addItems(self.known_explorers.keys())
        chain_combo.setCurrentIndex(self.known_explorers.keys().index(self.chain))

        chain_combo.currentIndexChanged.connect(self.on_chain_combo_changed)

        self.explorer_combo = explorer_combo = QComboBox()
        explorer_names_list = [i.name for i in self.known_explorers[self.chain]]
        explorer_combo.addItems(explorer_names_list)
        explorer_combo.setCurrentIndex(explorer_names_list.index(self.explorer.name))

        explorer_combo.currentIndexChanged.connect(self.on_explorer_combo_changed)

        form.addRow('Chain:', chain_combo)
        form.addRow('Explorer:', explorer_combo)
        form.addRow(floated_buttons([set_default_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #10
0
    def create_settings_tab(self):
        form = QFormLayout()

        self.user_edit = QLineEdit()
        self.user_edit.setText(self.profile.user)
        self.pass_edit = QLineEdit()
        self.pass_edit.setText(self.profile.password)
        self.host_edit = QLineEdit()
        self.host_edit.setText(self.profile.host)
        self.port_edit = QSpinBox()
        self.port_edit.setRange(0, 65535)
        self.port_edit.setValue(int(self.profile.port))

        for i in [self.user_edit, self.pass_edit, self.host_edit]:
            i.textChanged.connect(self.update_profile)
        self.port_edit.valueChanged.connect(self.update_profile)

        save_profile_button = QPushButton('Save')
        save_profile_button.clicked.connect(self.save_rpc_options)

        form.addRow('RPC Username:'******'RPC Password:'******'RPC Host:', self.host_edit)
        form.addRow('RPC Port:', self.port_edit)
        form.addRow(floated_buttons([save_profile_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #11
0
    def create_layout(self):
        # ComboBox for selecting which template to use.
        self.template_combo = QComboBox()
        self.template_combo.addItems([i.name for i in known_templates])
        self.setFocusProxy(self.template_combo)

        template = known_templates[0]
        self.template_widget = TemplateWidget(template)

        self.template_combo.currentIndexChanged.connect(self.change_template)

        # Generated script
        self.script_output = QPlainTextEdit()
        self.script_output.setReadOnly(True)
        self.script_output.setFont(monospace_font)

        self.generate_button = QPushButton('Generate')
        self.generate_button.clicked.connect(self.generate)

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel('Select a template:'))
        vbox.addWidget(self.template_combo)
        vbox.addWidget(self.template_widget)

        vbox.addWidget(QLabel('Generated script:'))
        vbox.addWidget(self.script_output)

        btn_hbox = floated_buttons([self.generate_button])
        vbox.addLayout(btn_hbox)

        return vbox
예제 #12
0
    def create_outputs_tab(self):
        form = QFormLayout()
        self.outputs_tree = OutputsTree()
        self.outputs_editor = OutputsEditor(self.handler.gui, self.outputs_tree)
        self.outputs_editor.setEnabled(False)

        def update_enabled_widgets():
            num_outputs = len(self.outputs_tree.get_outputs())
            self.outputs_editor.setEnabled(num_outputs > 0)

        def add_output():
            new_output = CMutableTxOut(0)
            self.outputs_tree.add_output(new_output)

            update_enabled_widgets()
            if len(self.outputs_tree.get_outputs()) > 0:
                self.outputs_tree.view.selectRow(self.outputs_tree.model.rowCount() - 1)

        update_enabled_widgets()

        add_output_button = QPushButton("New output")
        add_output_button.setToolTip("Add a new output")
        add_output_button.clicked.connect(add_output)

        form.addRow(self.outputs_tree)
        form.addRow(Separator())

        form.addRow(self.outputs_editor)

        form.addRow(Separator())
        form.addRow(floated_buttons([add_output_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #13
0
    def create_settings_tab(self):
        form = QFormLayout()

        self.user_edit = QLineEdit()
        self.user_edit.setText(self.profile.user)
        self.pass_edit = QLineEdit()
        self.pass_edit.setText(self.profile.password)
        self.host_edit = QLineEdit()
        self.host_edit.setText(self.profile.host)
        self.port_edit = QSpinBox()
        self.port_edit.setRange(0, 65535)
        self.port_edit.setValue(int(self.profile.port))

        for i in [self.user_edit, self.pass_edit, self.host_edit]:
            i.textChanged.connect(self.update_profile)
        self.port_edit.valueChanged.connect(self.update_profile)

        save_profile_button = QPushButton('Save')
        save_profile_button.clicked.connect(self.save_rpc_options)

        form.addRow('RPC Username:'******'RPC Password:'******'RPC Host:', self.host_edit)
        form.addRow('RPC Port:', self.port_edit)
        form.addRow(floated_buttons([save_profile_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #14
0
    def create_layout(self):
        # ComboBox for selecting which template to use.
        self.template_combo = QComboBox()
        self.template_combo.addItems([i.name for i in known_templates])
        self.setFocusProxy(self.template_combo)

        template = known_templates[0]
        self.template_widget = TemplateWidget(template)

        self.template_combo.currentIndexChanged.connect(self.change_template)

        # Generated script
        self.script_output = QPlainTextEdit()
        self.script_output.setReadOnly(True)
        self.script_output.setFont(monospace_font)

        self.generate_button = QPushButton('Generate')
        self.generate_button.clicked.connect(self.generate)

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel('Select a template:'))
        vbox.addWidget(self.template_combo)
        vbox.addWidget(self.template_widget)

        vbox.addWidget(QLabel('Generated script:'))
        vbox.addWidget(self.script_output)

        btn_hbox = floated_buttons([self.generate_button])
        vbox.addLayout(btn_hbox)

        return vbox
예제 #15
0
    def create_rpc_tab(self):
        form = QFormLayout()

        self.method_edit = QLineEdit()
        self.method_edit.setWhatsThis('Enter the RPC method you want to use here. Some methods have auto-completion support, but any method that a node accepts can be entered here.')
        method_completer = QCompleter(known_methods)
        method_completer.setCompletionMode(QCompleter.InlineCompletion)
        self.method_edit.setCompleter(method_completer)

        self.params_edit = QLineEdit()
        param_desc = QLabel('Params syntax is the same as when using a wallet\'s command-line tool (e.g. bitcoin-cli) from a shell.')

        self.result_edit = QPlainTextEdit()
        self.result_edit.setWhatsThis('The response from a node is displayed here.')
        self.result_edit.setReadOnly(True)
        self.result_edit.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)
        self.result_edit.setContextMenuPolicy(Qt.CustomContextMenu)
        self.result_edit.customContextMenuRequested.connect(self.context_menu)

        do_button = QPushButton('&Download')
        do_button.clicked.connect(self.call_rpc)

        form.addRow('&Method:', self.method_edit)
        form.addRow(param_desc)
        form.addRow('&Params:', self.params_edit)
        form.addRow('Result:', self.result_edit)
        form.addRow(floated_buttons([do_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #16
0
    def create_layout(self):
        # ComboBox for selecting which template to use.
        self.template_combo = QComboBox()
        self.template_combo.setWhatsThis("Use this to select a template for script generation.")
        self.template_combo.addItems([i.name for i in known_templates])
        self.setFocusProxy(self.template_combo)

        template = known_templates[0]
        self.template_widget = TemplateWidget(template)

        self.template_combo.currentIndexChanged.connect(self.change_template)

        # Generated script
        self.script_output = QPlainTextEdit()
        self.script_output.setWhatsThis("The generated script is displayed here in human-readable format.")
        self.script_output.setReadOnly(True)
        self.script_output.setFont(monospace_font)
        self.script_output.setContextMenuPolicy(Qt.CustomContextMenu)
        self.script_output.customContextMenuRequested.connect(self.context_menu)

        self.generate_button = QPushButton("Generate")
        self.generate_button.clicked.connect(self.generate)

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel("Select a template:"))
        vbox.addWidget(self.template_combo)
        vbox.addWidget(self.template_widget)

        vbox.addWidget(QLabel("Generated script:"))
        vbox.addWidget(self.script_output)

        btn_hbox = floated_buttons([self.generate_button])
        vbox.addLayout(btn_hbox)

        return vbox
예제 #17
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)
예제 #18
0
    def create_rpc_tab(self):
        form = QFormLayout()

        self.method_edit = QLineEdit()
        method_completer = QCompleter([i.method for i in known_methods])
        method_completer.setCompletionMode(QCompleter.InlineCompletion)
        self.method_edit.setCompleter(method_completer)

        self.params_edit = QLineEdit()
        param_desc = QLabel('Params syntax is the same as when using a wallet\'s command-line tool (e.g. bitcoin-cli) from a shell.')

        self.result_edit = QPlainTextEdit()
        self.result_edit.setReadOnly(True)
        self.result_edit.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)
        self.result_edit.setContextMenuPolicy(Qt.CustomContextMenu)
        self.result_edit.customContextMenuRequested.connect(self.context_menu)

        do_button = QPushButton('&Download')
        do_button.clicked.connect(self.call_rpc)

        form.addRow('&Method:', self.method_edit)
        form.addRow(param_desc)
        form.addRow('&Params:', self.params_edit)
        form.addRow('Result:', self.result_edit)
        form.addRow(floated_buttons([do_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #19
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)
예제 #20
0
    def create_layout(self):
        form = QFormLayout()

        self.model = VarsModel(self.data)
        self.proxy_model = VarsProxyModel()
        self.proxy_model.setSourceModel(self.model)

        self.view = QTableView()
        self.view.setWhatsThis('This table displays the variables you have defined.')
        self.view.setModel(self.proxy_model)
        self.view.setSortingEnabled(True)
        self.view.sortByColumn(0, QtCore.Qt.AscendingOrder)
        self.view.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)
        self.view.horizontalHeader().setHighlightSections(False)
        self.view.verticalHeader().setDefaultSectionSize(22)
        self.view.verticalHeader().setVisible(False)
        self.view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.view.customContextMenuRequested.connect(self.context_menu)
        self.view.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding))
        self.view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.view.setAlternatingRowColors(True)

        form.addRow(self.create_filters_box())
        form.addRow(self.view)

        # Controls for adding/removing variables

        self.new_var_key = QLineEdit()
        self.new_var_key.setPlaceholderText('Key')
        self.new_var_key.setWhatsThis('Enter the name to give the new variable here.')
        self.setFocusProxy(self.new_var_key)
        self.new_var_value = QLineEdit()
        self.new_var_value.setPlaceholderText('Value')
        self.new_var_value.setWhatsThis('Enter the value to give the new variable here.')
        add_var_btn = QPushButton('&Add')
        add_var_btn.clicked.connect(self.add_new_var)
        add_var_hbox = HBox(self.new_var_key, QLabel(':'), self.new_var_value, add_var_btn)

        self.auto_save_check = QCheckBox('Automatically save')
        self.auto_save_check.setWhatsThis('If this box is checked, then your stored variables will automatically be saved whenever one is added or deleted.')
        self.auto_save_check.setChecked(self.auto_save)
        def change_auto_save(is_checked):
            is_checked = True if is_checked else False
            self.auto_save = is_checked
            self.set_option('auto_save', self.auto_save)
        self.auto_save_check.stateChanged.connect(change_auto_save)
        self.save_button = QPushButton('Save')
        self.save_button.clicked.connect(self.save_variables)
        self.save_button.setToolTip('Save variables to config file')
        self.save_button.setWhatsThis('This button will save your stored variables in the Hashmal config file.')

        form.addRow('Add:', add_var_hbox)
        form.addRow(floated_buttons([self.auto_save_check, self.save_button]))
        return form
예제 #21
0
    def create_layout(self):
        form = QFormLayout()

        self.model = VarsModel(self.data)

        self.view = QTableView()
        self.view.setModel(self.model)
        self.view.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)
        self.view.horizontalHeader().setHighlightSections(False)
        self.view.verticalHeader().setDefaultSectionSize(22)
        self.view.verticalHeader().setVisible(False)
        self.view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.view.customContextMenuRequested.connect(self.context_menu)
        self.view.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding))
        self.view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.view.setAlternatingRowColors(True)

        self.filter_combo = QComboBox()
        self.filter_combo.addItems(self.filters)
        self.filter_combo.currentIndexChanged.connect(self.filter_table)

        form.addRow('Filter:', self.filter_combo)
        form.addRow(self.view)

        # Controls for adding/removing variables

        self.new_var_key = QLineEdit()
        self.setFocusProxy(self.new_var_key)
        self.new_var_value = QLineEdit()
        add_var_btn = QPushButton('Set')
        add_var_btn.clicked.connect(self.add_new_var)
        add_var_hbox = HBox(self.new_var_key, QLabel(':'), self.new_var_value, add_var_btn)

        self.del_var_key = QLineEdit()
        del_var_button = QPushButton('Delete')
        del_var_button.clicked.connect(self.remove_var)
        del_var_hbox = HBox(self.del_var_key, del_var_button)

        self.auto_save_check = QCheckBox('Automatically save')
        self.auto_save_check.setChecked(self.auto_save)
        def change_auto_save(is_checked):
            is_checked = True if is_checked else False
            self.auto_save = is_checked
            self.set_option('auto_save', self.auto_save)
        self.auto_save_check.stateChanged.connect(change_auto_save)
        self.save_button = QPushButton('Save')
        self.save_button.clicked.connect(self.save_variables)
        self.save_button.setToolTip('Save variables to config file')

        form.addRow('Add:', add_var_hbox)
        form.addRow('Delete:', del_var_hbox)
        form.addRow(floated_buttons([self.auto_save_check, self.save_button]))
        return form
예제 #22
0
    def create_verify_tab(self):
        form = QFormLayout()
        form.setRowWrapPolicy(QFormLayout.WrapLongRows)

        self.inputs_box = QSpinBox()
        self.inputs_box.setToolTip('Input to verify')

        self.verify_button = QPushButton('Verify')
        self.verify_button.clicked.connect(self.verify_input)
        self.verify_button.setToolTip('Verify an input')
        self.verify_button.setWhatsThis('This button will attempt to verify an input.\n\nIf no plugin is available to retrieve blockchain data, such as the "Blockchain" or "Wallet RPC" plugins, this will not function. The plugin used to retrieve blockchain data can be changed in the Settings dialog.')

        self.verify_all_button = QPushButton('Verify All')
        self.verify_all_button.clicked.connect(self.verify_inputs)
        self.verify_all_button.setToolTip('Verify all inputs')
        self.verify_all_button.setWhatsThis('This button will attempt to verify all inputs.\n\nIf no plugin is available to retrieve blockchain data, such as the "Blockchain" or "Wallet RPC" plugins, this will not function. The plugin used to retrieve blockchain data can be changed in the Settings dialog.')

        self.result_edit = QLineEdit()
        self.result_edit.setToolTip('Verification result')
        self.result_edit.setWhatsThis('The result of verifying an input is shown here.')
        self.result_edit.setReadOnly(True)

        self.inputs_table_model = InputsStatusModel()
        self.inputs_table = QTableView()
        self.inputs_table.setModel(self.inputs_table_model)
        self.inputs_table.horizontalHeader().setResizeMode(0, QHeaderView.ResizeToContents)
        self.inputs_table.horizontalHeader().setResizeMode(2, QHeaderView.Stretch)
        self.inputs_table.verticalHeader().setVisible(False)
        for i in [self.inputs_table.horizontalHeader(), self.inputs_table.verticalHeader()]:
            i.setHighlightSections(False)
        self.inputs_table.setToolTip('Verification results')
        self.inputs_table.setWhatsThis('This table displays which inputs you have verified for the transaction being analyzed.')

        form.addRow('Verify Input:', floated_buttons([self.inputs_box, self.verify_button]))
        form.addRow(floated_buttons([self.verify_all_button]))
        form.addRow('Result:', self.result_edit)
        form.addRow(self.inputs_table)

        w = QWidget()
        w.setLayout(form)
        return w
예제 #23
0
    def create_main_tab(self):
        form = QFormLayout()
        form.setRowWrapPolicy(QFormLayout.WrapAllRows)

        # Raw script input.
        self.tx_script = QPlainTextEdit()
        self.tx_script.textChanged.connect(self.reset_step_counter)
        self.tx_script.setFont(monospace_font)
        # Result of the latest script op.
        self.stack_result = QLineEdit()
        self.stack_result.setReadOnly(True)

        # Visualization of stack.
        self.stack_view = QListWidget()
        # Log of script ops.
        self.stack_log = QTreeWidget()
        self.stack_log.setColumnCount(3)
        self.stack_log.setHeaderLabels(['Step', 'Op', 'Result'])
        self.stack_log.header().setDefaultSectionSize(50)
        self.stack_log.header().setResizeMode(0, QHeaderView.Fixed)
        self.stack_log.header().setResizeMode(1, QHeaderView.ResizeToContents)
        self.stack_log.header().setResizeMode(2, QHeaderView.Stretch)
        self.stack_log.setSizePolicy(QSizePolicy.Preferred,
                                     QSizePolicy.Expanding)

        # Controls
        self.step_button = QPushButton('Step')
        self.step_button.setToolTip('Evaluate the next operation')
        self.step_button.clicked.connect(self.do_step)
        self.reset_button = QPushButton('Reset')
        self.reset_button.setToolTip('Reset the current evaluation')
        self.reset_button.clicked.connect(self.reset)
        self.do_button = QPushButton('Evaluate')
        self.do_button.setToolTip('Evaluate the entire script')
        self.do_button.clicked.connect(self.do_evaluate)

        form.addRow('Script:', self.tx_script)
        form.addRow('Stack:', self.stack_view)
        form.addRow('Stack log:', self.stack_log)
        form.addRow(self.stack_result)

        btn_hbox = floated_buttons(
            [self.step_button, self.reset_button, self.do_button], left=True)
        form.addRow(btn_hbox)

        w = QWidget()
        w.setLayout(form)
        return w
예제 #24
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)
예제 #25
0
    def create_deserialize_tab(self):
        form = QFormLayout()

        self.deserialize_button = QPushButton('Deserialize')
        self.deserialize_button.clicked.connect(self.deserialize)
        btn_hbox = floated_buttons([self.deserialize_button])

        self.tx_widget = TxWidget()
        self.tx_widget.inputs_tree.view.customContextMenuRequested.disconnect(self.tx_widget.inputs_tree.customContextMenu)
        self.tx_widget.inputs_tree.view.customContextMenuRequested.connect(self.inputs_context_menu)

        form.addRow(self.tx_widget)

        w = QWidget()
        w.setLayout(form)
        return w
예제 #26
0
파일: stack.py 프로젝트: oktoshi/hashmal
    def create_main_tab(self):
        form = QFormLayout()
        form.setRowWrapPolicy(QFormLayout.WrapAllRows)

        # Raw script input.
        self.tx_script = QPlainTextEdit()
        self.tx_script.textChanged.connect(self.reset_step_counter)
        self.tx_script.setFont(monospace_font)
        # Result of the latest script op.
        self.stack_result = QLineEdit()
        self.stack_result.setReadOnly(True)

        # Visualization of stack.
        self.stack_view = QListWidget()
        # Log of script ops.
        self.stack_log = QTreeWidget()
        self.stack_log.setColumnCount(3)
        self.stack_log.setHeaderLabels(['Step', 'Op', 'Result'])
        self.stack_log.header().setDefaultSectionSize(50)
        self.stack_log.header().setResizeMode(0, QHeaderView.Fixed)
        self.stack_log.header().setResizeMode(1, QHeaderView.ResizeToContents)
        self.stack_log.header().setResizeMode(2, QHeaderView.Stretch)
        self.stack_log.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)

        # Controls
        self.step_button = QPushButton('Step')
        self.step_button.setToolTip('Evaluate the next operation')
        self.step_button.clicked.connect(self.do_step)
        self.reset_button = QPushButton('Reset')
        self.reset_button.setToolTip('Reset the current evaluation')
        self.reset_button.clicked.connect(self.reset)
        self.do_button = QPushButton('Evaluate')
        self.do_button.setToolTip('Evaluate the entire script')
        self.do_button.clicked.connect(self.do_evaluate)


        form.addRow('Script:', self.tx_script)
        form.addRow('Stack:', self.stack_view)
        form.addRow('Stack log:', self.stack_log)
        form.addRow(self.stack_result)

        btn_hbox = floated_buttons([self.step_button, self.reset_button, self.do_button], left=True)
        form.addRow(btn_hbox)

        w = QWidget()
        w.setLayout(form)
        return w
예제 #27
0
파일: tx.py 프로젝트: mazaclub/hashmal
    def __init__(self, parent=None):
        super(TxProperties, self).__init__(parent)
        self.tx_size_edit = QLineEdit()
        self.tx_size_edit.setReadOnly(True)
        tx_size = HBox(QLabel('Size:'), self.tx_size_edit)
        tx_size.setContentsMargins(0, 0, 0, 0)
        self.tx_size = QWidget()
        self.tx_size.setLayout(tx_size)
        self.tx_size.setToolTip('Size (in bytes) of the serialized tx')

        self.is_final = ReadOnlyCheckBox('Is Final')
        self.is_final.setToolTip('True if all inputs have a Sequence of 0xffffffff')
        self.is_coinbase = ReadOnlyCheckBox('Is Coinbase')
        self.is_coinbase.setToolTip('True if the tx generates new coins via mining')
        hbox = floated_buttons([self.tx_size, self.is_final, self.is_coinbase], left=True)
        hbox.setContentsMargins(16, 0, 0, 0)
        self.setLayout(hbox)
예제 #28
0
 def create_layout(self):
     form = QFormLayout()
     scroller = QScrollArea()
     self.clear_button = QPushButton('Clear')
     self.clear_button.clicked.connect(self.clear_fields)
     for var_name in self.template.variables.keys():
         label = QLabel(''.join([var_name.capitalize(), ':']))
         var_input = QLineEdit()
         var_input.setFont(monospace_font)
         var_input.setToolTip('Value for template variable "%s"' % var_name)
         form.addRow(label, var_input)
         self.variable_widgets[var_name] = var_input
     form.addRow(floated_buttons([self.clear_button], left=True))
     scroller.setLayout(form)
     while self.layout().count() > 0:
         self.layout().takeAt(0)
     self.layout().addWidget(scroller)
예제 #29
0
 def create_layout(self):
     form = QFormLayout()
     scroller = QScrollArea()
     self.clear_button = QPushButton('Clear')
     self.clear_button.clicked.connect(self.clear_fields)
     for var_name in self.template.variables.keys():
         label = QLabel(''.join([var_name.capitalize(), ':']))
         var_input = QLineEdit()
         var_input.setFont(monospace_font)
         var_input.setToolTip('Value for template variable "%s"' % var_name)
         form.addRow(label, var_input)
         self.variable_widgets[var_name] = var_input
     form.addRow(floated_buttons([self.clear_button], left=True))
     scroller.setLayout(form)
     while self.layout().count() > 0:
         self.layout().takeAt(0)
     self.layout().addWidget(scroller)
예제 #30
0
    def create_download_tab(self):
        form = QFormLayout()
        form.setRowWrapPolicy(QFormLayout.WrapAllRows)

        self.data_group = QButtonGroup()
        self.data_box = QGroupBox()
        hbox = QHBoxLayout()
        hbox.setContentsMargins(0, 0, 0, 6)
        for i, data_type in enumerate(known_data_types.keys()):
            btn = QRadioButton(data_type)
            self.data_group.addButton(btn, i)
            hbox.addWidget(btn)
        hbox.addStretch(1)
        self.data_box.setLayout(hbox)

        self.id_edit = QLineEdit()
        self.id_edit.setWhatsThis(
            'Enter an identifier here, such as a transaction ID or block hash.'
        )
        self.raw_edit = QTextEdit()
        self.raw_edit.setReadOnly(True)
        self.raw_edit.setWhatsThis(
            'The result of a download is displayed here.')
        self.raw_edit.setContextMenuPolicy(Qt.CustomContextMenu)
        self.raw_edit.customContextMenuRequested.connect(self.context_menu)
        self.download_button = QPushButton('&Download')
        self.download_button.clicked.connect(self.do_download)
        self.download_button.setEnabled(False)

        def validate_identifier(txt):
            valid = len(str(txt)) == 64
            self.download_button.setEnabled(valid)

        self.id_edit.textChanged.connect(validate_identifier)

        form.addRow(self.data_box)
        form.addRow('Identifier (Transaction ID or Block Hash):', self.id_edit)
        form.addRow(floated_buttons([self.download_button]))
        form.addRow('Result:', self.raw_edit)

        self.data_group.buttonClicked.connect(lambda: self.raw_edit.clear())

        w = QWidget()
        w.setLayout(form)
        return w
예제 #31
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_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)
예제 #32
0
    def create_deserialize_tab(self):
        form = QFormLayout()

        self.deserialize_button = QPushButton('Deserialize')
        self.deserialize_button.clicked.connect(self.deserialize)
        btn_hbox = floated_buttons([self.deserialize_button])

        self.tx_widget = TxWidget()
        self.tx_widget.inputs_tree.view.customContextMenuRequested.disconnect(
            self.tx_widget.inputs_tree.customContextMenu)
        self.tx_widget.inputs_tree.view.customContextMenuRequested.connect(
            self.inputs_context_menu)

        form.addRow(self.tx_widget)

        w = QWidget()
        w.setLayout(form)
        return w
예제 #33
0
    def create_download_tab(self):
        form = QFormLayout()
        
        self.tx_id_edit = QLineEdit()
        self.raw_tx_edit = QTextEdit()
        self.raw_tx_edit.setReadOnly(True)
        self.raw_tx_edit.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.raw_tx_edit.customContextMenuRequested.connect(self.context_menu)
        self.download_button = QPushButton('Download')
        self.download_button.clicked.connect(self.do_download)

        form.addRow('Tx ID:', self.tx_id_edit)
        form.addRow(floated_buttons([self.download_button]))
        form.addRow('Raw Tx:', self.raw_tx_edit)

        w = QWidget()
        w.setLayout(form)
        return w
예제 #34
0
    def create_explorer_tab(self):
        form = QFormLayout()

        set_default_button = QPushButton('Save as default')
        set_default_button.setToolTip('Save this block explorer as default')

        def set_default():
            chain = str(chain_combo.currentText())
            txt = str(explorer_combo.currentText())
            self.set_option('chain', chain)
            self.set_option('explorer', txt)

        set_default_button.clicked.connect(set_default)

        self.chain_combo = chain_combo = QComboBox()
        chain_combo.setWhatsThis(
            'Use this to select which cryptocurrency\'s block explorers you want to use.'
        )
        chain_combo.addItems(self.known_explorers.keys())
        chain_combo.setCurrentIndex(self.known_explorers.keys().index(
            self.chain))

        chain_combo.currentIndexChanged.connect(self.on_chain_combo_changed)

        self.explorer_combo = explorer_combo = QComboBox()
        explorer_combo.setWhatsThis(
            'Use this to select which block explorer you want to use.')
        explorer_names_list = [
            i.name for i in self.known_explorers[self.chain]
        ]
        explorer_combo.addItems(explorer_names_list)
        explorer_combo.setCurrentIndex(
            explorer_names_list.index(self.explorer.name))

        explorer_combo.currentIndexChanged.connect(
            self.on_explorer_combo_changed)

        form.addRow('Chain:', chain_combo)
        form.addRow('Explorer:', explorer_combo)
        form.addRow(floated_buttons([set_default_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #35
0
    def create_review_tab(self):
        form = QFormLayout()

        self.raw_tx = QTextEdit()
        self.raw_tx.setReadOnly(True)

        self.tx_widget = TxWidget()

        build_button = QPushButton('Build transaction')
        build_button.setToolTip('Build a tx from the data in the previous tabs')
        build_button.clicked.connect(self.build_transaction)

        form.addRow('Raw Tx:', self.raw_tx)
        form.addRow(self.tx_widget)
        form.addRow(floated_buttons([build_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #36
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_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)
예제 #37
0
    def create_download_tab(self):
        form = QFormLayout()
        form.setRowWrapPolicy(QFormLayout.WrapAllRows)

        self.data_group = QButtonGroup()
        self.data_box = QGroupBox()
        hbox = QHBoxLayout()
        hbox.setContentsMargins(0, 0, 0, 6)
        for i, data_type in enumerate(known_data_types.keys()):
            btn = QRadioButton(data_type)
            self.data_group.addButton(btn, i)
            hbox.addWidget(btn)
        hbox.addStretch(1)
        self.data_box.setLayout(hbox)

        self.id_edit = QLineEdit()
        self.id_edit.setWhatsThis("Enter an identifier here, such as a transaction ID or block hash.")
        self.raw_edit = QTextEdit()
        self.raw_edit.setReadOnly(True)
        self.raw_edit.setWhatsThis("The result of a download is displayed here.")
        self.raw_edit.setContextMenuPolicy(Qt.CustomContextMenu)
        self.raw_edit.customContextMenuRequested.connect(self.context_menu)
        self.download_button = QPushButton("&Download")
        self.download_button.clicked.connect(self.do_download)
        self.download_button.setEnabled(False)

        def validate_identifier(txt):
            valid = len(str(txt)) == 64
            self.download_button.setEnabled(valid)

        self.id_edit.textChanged.connect(validate_identifier)

        form.addRow(self.data_box)
        form.addRow("Identifier (Transaction ID or Block Hash):", self.id_edit)
        form.addRow(floated_buttons([self.download_button]))
        form.addRow("Result:", self.raw_edit)

        self.data_group.buttonClicked.connect(lambda: self.raw_edit.clear())

        w = QWidget()
        w.setLayout(form)
        return w
예제 #38
0
    def create_layout(self):
        # ComboBox for selecting which template to use.
        self.template_combo = QComboBox()
        self.template_combo.setWhatsThis(
            'Use this to select a template for script generation.')
        self.template_combo.addItems([i.name for i in known_templates])
        self.setFocusProxy(self.template_combo)

        template = known_templates[0]
        self.template_widget = TemplateWidget(template)

        self.template_combo.currentIndexChanged.connect(self.change_template)

        # Generated script
        self.script_output = QPlainTextEdit()
        self.script_output.setWhatsThis(
            'The generated script is displayed here in human-readable format.')
        self.script_output.setReadOnly(True)
        self.script_output.setFont(monospace_font)
        self.script_output.setContextMenuPolicy(Qt.CustomContextMenu)
        self.script_output.customContextMenuRequested.connect(
            self.context_menu)

        self.generate_button = QPushButton('Generate')
        self.generate_button.clicked.connect(self.generate)
        self.generate_button.setToolTip('Generate script')
        self.generate_button.setWhatsThis(
            'Clicking this button will generate a script based on the chosen template.'
        )

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel('Select a template:'))
        vbox.addWidget(self.template_combo)
        vbox.addWidget(self.template_widget)

        btn_hbox = floated_buttons([self.generate_button])
        vbox.addLayout(btn_hbox)

        vbox.addWidget(QLabel('Generated script:'))
        vbox.addWidget(self.script_output)

        return vbox
예제 #39
0
    def create_api_tab(self):
        form = QFormLayout()

        config_apis = self.config.get_option('blockchain_apis')
        config_domain = config_apis.get(self.api.api_name(), self.api.api_type.default_domain)

        api_domain_edit = QLineEdit()
        api_domain_edit.setText(config_domain)
        reset_domain_button = QPushButton('Reset to Default')
        reset_domain_button.setToolTip('Reset domain to the API\'s default')
        save_domain_button = QPushButton('Save Domain')
        save_domain_button.setToolTip('Save domain to use with this API')

        api_type_combo = QComboBox()
        api_type_combo.addItems([i.name for i in known_api_types])

        def change_api_type(idx):
            new_api = known_api_types[idx]
            self.set_api_type(new_api)
            api_domain_edit.setText(self.api.domain)
        api_type_combo.currentIndexChanged.connect(change_api_type)

        def change_api_domain():
            txt = str(api_domain_edit.text())
            if not txt: return
            self.set_api_domain(txt)

        def reset_api_domain():
            default = self.api.api_type.default_domain
            api_domain_edit.setText(default)
            change_api_domain()

        reset_domain_button.clicked.connect(reset_api_domain)
        save_domain_button.clicked.connect(change_api_domain)

        form.addRow('API:', api_type_combo)
        form.addRow('Domain:', api_domain_edit)
        form.addRow(floated_buttons([reset_domain_button, save_domain_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #40
0
    def create_layout(self):
        form = QFormLayout()
        form.setRowWrapPolicy(QFormLayout.WrapLongRows)


        self.raw_tx_edit = QPlainTextEdit()
        self.raw_tx_edit.setFont(monospace_font)

        self.deserialize_button = QPushButton('Deserialize')
        self.deserialize_button.clicked.connect(self.deserialize)
        btn_hbox = floated_buttons([self.deserialize_button])

        self.tx_widget = TxWidget()

        form.addRow('Raw Tx:', self.raw_tx_edit)
        form.addRow(btn_hbox)
        form.addRow(Separator())
        form.addRow(self.tx_widget)

        return form
예제 #41
0
    def __init__(self, parent=None):
        super(TxProperties, self).__init__(parent)
        self.tx_size_edit = QLineEdit()
        self.tx_size_edit.setReadOnly(True)
        tx_size = HBox(QLabel('Size:'), self.tx_size_edit)
        tx_size.setContentsMargins(0, 0, 0, 0)
        self.tx_size = QWidget()
        self.tx_size.setLayout(tx_size)
        self.tx_size.setToolTip('Size (in bytes) of the serialized tx')

        self.is_final = ReadOnlyCheckBox('Is Final')
        self.is_final.setToolTip(
            'True if all inputs have a Sequence of 0xffffffff')
        self.is_coinbase = ReadOnlyCheckBox('Is Coinbase')
        self.is_coinbase.setToolTip(
            'True if the tx generates new coins via mining')
        hbox = floated_buttons([self.tx_size, self.is_final, self.is_coinbase],
                               left=True)
        hbox.setContentsMargins(16, 0, 0, 0)
        self.setLayout(hbox)
예제 #42
0
    def create_inputs_tab(self):
        form = QFormLayout()
        self.inputs_tree = InputsTree()
        self.inputs_tree.view.setWhatsThis(
            'The inputs of your transaction are displayed here.')
        self.inputs_editor = InputsEditor(self.handler.gui, self.inputs_tree)
        self.inputs_editor.setEnabled(False)

        def update_enabled_widgets():
            num_inputs = len(self.inputs_tree.get_inputs())
            self.inputs_editor.setEnabled(num_inputs > 0)

        def add_input():
            outpoint = CMutableOutPoint(n=0)
            new_input = CMutableTxIn(prevout=outpoint)
            self.inputs_tree.add_input(new_input)

            update_enabled_widgets()
            if len(self.inputs_tree.get_inputs()) > 0:
                self.inputs_tree.view.selectRow(
                    self.inputs_tree.model.rowCount() - 1)

        update_enabled_widgets()

        add_input_button = QPushButton('New input')
        add_input_button.setToolTip('Add a new input')
        add_input_button.setWhatsThis(
            'Clicking this button will add a new input to your transaction.')
        add_input_button.clicked.connect(add_input)

        form.addRow(self.inputs_tree)
        form.addRow(Separator())

        form.addRow(self.inputs_editor)

        form.addRow(Separator())
        form.addRow(floated_buttons([add_input_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #43
0
    def create_layout(self):
        # ComboBox for selecting which template to use.
        self.template_combo = QComboBox()
        for i in self.templates:
            if isinstance(i, str):
                self.template_combo.insertSeparator(
                    self.template_combo.count())
            else:
                self.template_combo.addItem(i.name)

        # StackedWidget showing input widgets for the currently selected template.
        self.template_stack = QStackedWidget()
        for i in self.templates:
            if isinstance(i, str):
                # separator
                continue
            self.template_stack.addWidget(i)

        self.template_combo.currentIndexChanged.connect(self.change_template)

        # Generated script
        self.script_output = QPlainTextEdit()
        self.script_output.setReadOnly(True)
        self.script_output.setFont(monospace_font)

        self.generate_button = QPushButton('Generate')
        self.generate_button.clicked.connect(self.generate)

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel('Select a template:'))
        vbox.addWidget(self.template_combo)
        vbox.addWidget(self.template_stack)

        vbox.addWidget(QLabel('Generated script:'))
        vbox.addWidget(self.script_output)

        btn_hbox = floated_buttons([self.generate_button])
        vbox.addLayout(btn_hbox)

        return vbox
예제 #44
0
    def create_main_tab(self):
        self.execution_widget = ScriptExecutionWidget(self.execution)
        # For variable substitution
        self.execution_widget.model.plugin_handler = self.handler

        self.execution_delegate = ScriptExecutionDelegate()
        self.execution_widget.view.setItemDelegate(self.execution_delegate)

        # Raw script input.
        self.tx_script = QPlainTextEdit()
        self.tx_script.setWhatsThis('Enter a raw script here to evaluate it.')
        self.tx_script.setFont(monospace_font)
        self.tx_script.setTabChangesFocus(True)

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel('Script:'))
        vbox.addWidget(self.tx_script)
        vbox.addWidget(self.execution_widget, stretch=1)

        self.clear_button = QPushButton('Clear')
        self.clear_button.setToolTip('Clear the current script.')
        self.clear_button.clicked.connect(self.reset)
        self.do_button = QPushButton('&Evaluate')
        self.do_button.setToolTip('Evaluate the entire script.')
        self.do_button.clicked.connect(self.do_evaluate)

        self.next_button = QPushButton('Next')
        self.next_button.setToolTip('Step forward in script execution.')
        self.next_button.clicked.connect(self.execution_widget.select_next)
        self.prev_button = QPushButton('Previous')
        self.prev_button.setToolTip('Step backward in script execution.')
        self.prev_button.clicked.connect(self.execution_widget.select_prev)

        btn_hbox = floated_buttons([self.clear_button, self.do_button, self.prev_button, self.next_button], left=True)
        vbox.addLayout(btn_hbox)

        w = QWidget()
        w.setLayout(vbox)
        return w
예제 #45
0
    def create_layout(self):
        # ComboBox for selecting which template to use.
        self.template_combo = QComboBox()
        for i in self.templates:
            if isinstance(i, str):
                self.template_combo.insertSeparator(self.template_combo.count())
            else:
                self.template_combo.addItem(i.name)

        # StackedWidget showing input widgets for the currently selected template.
        self.template_stack = QStackedWidget()
        for i in self.templates:
            if isinstance(i, str):
                # separator
                continue
            self.template_stack.addWidget(i)

        self.template_combo.currentIndexChanged.connect(self.change_template)

        # Generated script
        self.script_output = QPlainTextEdit()
        self.script_output.setReadOnly(True)
        self.script_output.setFont(monospace_font)

        self.generate_button = QPushButton('Generate')
        self.generate_button.clicked.connect(self.generate)

        vbox = QVBoxLayout()
        vbox.addWidget(QLabel('Select a template:'))
        vbox.addWidget(self.template_combo)
        vbox.addWidget(self.template_stack)

        vbox.addWidget(QLabel('Generated script:'))
        vbox.addWidget(self.script_output)

        btn_hbox = floated_buttons([self.generate_button])
        vbox.addLayout(btn_hbox)

        return vbox
예제 #46
0
    def create_layout(self):
        form = QFormLayout()
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels([ 'Key', 'Value' ])
        self.table.verticalHeader().setDefaultSectionSize(25)
        self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        self.table.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.table.customContextMenuRequested.connect(self.context_menu)
        self.table.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding))

        form.addRow(self.table)

        add_var_hbox = QHBoxLayout()
        self.new_var_key = QLineEdit()
        self.new_var_value = QLineEdit()
        add_var_hbox.addWidget(self.new_var_key)
        add_var_hbox.addWidget(QLabel(':'))
        add_var_hbox.addWidget(self.new_var_value)
        add_var_btn = QPushButton('Add')
        add_var_btn.clicked.connect(self.add_new_var)
        add_var_hbox.addWidget(add_var_btn)

        self.del_var_key = QLineEdit()
        del_var_button = QPushButton('Delete')
        del_var_button.clicked.connect(self.remove_var)
        del_var_hbox = QHBoxLayout()
        del_var_hbox.addWidget(self.del_var_key)
        del_var_hbox.addWidget(del_var_button)

        self.save_button = QPushButton('Save')
        self.save_button.clicked.connect(self.save_variables)
        self.save_button.setToolTip('Save variables to config file')

        form.addRow('Add:', add_var_hbox)
        form.addRow('Delete:', del_var_hbox)
        form.addRow(floated_buttons([self.save_button]))
        return form
예제 #47
0
    def create_inputs_tab(self):
        form = QFormLayout()
        self.inputs_tree = InputsTree()
        self.inputs_tree.view.setWhatsThis('The inputs of your transaction are displayed here.')
        self.inputs_editor = InputsEditor(self.handler.gui, self.inputs_tree)
        self.inputs_editor.setEnabled(False)

        def update_enabled_widgets():
            num_inputs = len(self.inputs_tree.get_inputs())
            self.inputs_editor.setEnabled(num_inputs > 0)

        def add_input():
            outpoint = CMutableOutPoint(n=0)
            new_input = CMutableTxIn(prevout=outpoint)
            self.inputs_tree.add_input(new_input)

            update_enabled_widgets()
            if len(self.inputs_tree.get_inputs()) > 0:
                self.inputs_tree.view.selectRow(self.inputs_tree.model.rowCount() - 1)

        update_enabled_widgets()

        add_input_button = QPushButton('New input')
        add_input_button.setToolTip('Add a new input')
        add_input_button.setWhatsThis('Clicking this button will add a new input to your transaction.')
        add_input_button.clicked.connect(add_input)

        form.addRow(self.inputs_tree)
        form.addRow(Separator())

        form.addRow(self.inputs_editor)

        form.addRow(Separator())
        form.addRow(floated_buttons([add_input_button]))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #48
0
    def create_layout(self):
        form = QFormLayout()

        self.model = VarsModel(self.data)
        self.proxy_model = VarsProxyModel()
        self.proxy_model.setSourceModel(self.model)

        self.view = QTableView()
        self.view.setWhatsThis(
            'This table displays the variables you have defined.')
        self.view.setModel(self.proxy_model)
        self.view.setSortingEnabled(True)
        self.view.sortByColumn(0, QtCore.Qt.AscendingOrder)
        self.view.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)
        self.view.horizontalHeader().setHighlightSections(False)
        self.view.verticalHeader().setDefaultSectionSize(22)
        self.view.verticalHeader().setVisible(False)
        self.view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.view.customContextMenuRequested.connect(self.context_menu)
        self.view.setSizePolicy(
            QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding))
        self.view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.view.setAlternatingRowColors(True)

        form.addRow(self.create_filters_box())
        form.addRow(self.view)

        # Controls for adding/removing variables

        self.new_var_key = QLineEdit()
        self.new_var_key.setPlaceholderText('Key')
        self.new_var_key.setWhatsThis(
            'Enter the name to give the new variable here.')
        self.setFocusProxy(self.new_var_key)
        self.new_var_value = QLineEdit()
        self.new_var_value.setPlaceholderText('Value')
        self.new_var_value.setWhatsThis(
            'Enter the value to give the new variable here.')
        add_var_btn = QPushButton('&Add')
        add_var_btn.clicked.connect(self.add_new_var)
        add_var_hbox = HBox(self.new_var_key, QLabel(':'), self.new_var_value,
                            add_var_btn)

        self.auto_save_check = QCheckBox('Automatically save')
        self.auto_save_check.setWhatsThis(
            'If this box is checked, then your stored variables will automatically be saved whenever one is added or deleted.'
        )
        self.auto_save_check.setChecked(self.auto_save)

        def change_auto_save(is_checked):
            is_checked = True if is_checked else False
            self.auto_save = is_checked
            self.set_option('auto_save', self.auto_save)

        self.auto_save_check.stateChanged.connect(change_auto_save)
        self.save_button = QPushButton('Save')
        self.save_button.clicked.connect(self.save_variables)
        self.save_button.setToolTip('Save variables to config file')
        self.save_button.setWhatsThis(
            'This button will save your stored variables in the Hashmal config file.'
        )

        form.addRow('Add:', add_var_hbox)
        form.addRow(floated_buttons([self.auto_save_check, self.save_button]))
        return form
예제 #49
0
    def create_inputs_tab(self):
        form = QFormLayout()
        self.inputs_tree = InputsTree()

        input_prev_tx = QLineEdit()
        input_prev_tx.setToolTip('Transaction ID of the tx with the output being spent')

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

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

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

        rm_input_edit = QSpinBox()
        rm_input_edit.setRange(0, 0)
        rm_input_button = QPushButton('Remove input')

        def add_input():
            try:
                outpoint = COutPoint(lx(str(input_prev_tx.text())), input_prev_vout.get_amount())
                in_script = Script.from_human(str(input_script.toPlainText()))
                new_input = CTxIn(outpoint, in_script.get_hex().decode('hex'), input_sequence.get_amount())
            except Exception as e:
                self.status_message(str(e), True)
                return
            else:
                self.inputs_tree.add_input(new_input)
                rm_input_edit.setRange(0, len(self.inputs_tree.get_inputs()) - 1)

        def rm_input():
            in_num = rm_input_edit.value()
            self.inputs_tree.model.takeRow(in_num)
            rm_input_edit.setRange(0, len(self.inputs_tree.get_inputs()) - 1)

        add_input_button = QPushButton('Add input')
        add_input_button.setToolTip('Add the above input')
        add_input_button.clicked.connect(add_input)

        rm_input_button.clicked.connect(rm_input)

        for i in [input_prev_tx, input_prev_vout, input_script, input_sequence]:
            i.setFont(monospace_font)

        form.addRow(self.inputs_tree)
        form.addRow(Separator())

        form.addRow('Previous Transaction:', input_prev_tx)
        form.addRow('Previous Tx Output:', input_prev_vout)
        form.addRow('Input script:', input_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(input_sequence, maxify_input_sequence))

        form.addRow(Separator())
        form.addRow(floated_buttons([add_input_button]))
        form.addRow('Remove input:', HBox(rm_input_edit, rm_input_button))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #50
0
    def create_outputs_tab(self):
        form = QFormLayout()
        self.outputs_tree = OutputsTree()

        output_value = QLineEdit()

        output_script = QTextEdit()
        output_script.setToolTip('Script that will be put on the stack after the input that spends it.')

        rm_output_edit = QSpinBox()
        rm_output_edit.setRange(0, 0)
        rm_output_button = QPushButton('Remove output')

        def add_output():
            try:
                val_str = str(output_value.text())
                value = 0
                if '.' in val_str:
                    value = int(float(val_str) * pow(10, 8))
                else:
                    value = int(val_str)
                out_script = Script.from_human(str(output_script.toPlainText()))
                new_output = CTxOut(value, out_script.get_hex().decode('hex'))
            except Exception as e:
                self.status_message(str(e), True)
                return
            else:
                self.outputs_tree.add_output(new_output)
                rm_output_edit.setRange(0, len(self.outputs_tree.get_outputs()) - 1)

        def rm_output():
            out_n = rm_output_edit.value()
            self.outputs_tree.model.takeRow(out_n)
            rm_output_edit.setRange(0, len(self.outputs_tree.get_outputs()) - 1)

        add_output_button = QPushButton('Add output')
        add_output_button.setToolTip('Add the above output')
        add_output_button.clicked.connect(add_output)

        rm_output_button.clicked.connect(rm_output)

        value_desc = QLabel('Include a decimal point if this value is not in satoshis.')
        value_desc.setWordWrap(True)

        for i in [output_value, output_script]:
            i.setFont(monospace_font)

        form.addRow(self.outputs_tree)
        form.addRow(Separator())

        form.addRow(value_desc)
        form.addRow('Value:', output_value)
        form.addRow('Output script:', output_script)

        form.addRow(Separator())
        form.addRow(floated_buttons([add_output_button]))
        form.addRow('Remove output:', HBox(rm_output_edit, rm_output_button))

        w = QWidget()
        w.setLayout(form)
        return w
예제 #51
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)