def test_P2SH(self): script_hex = 'a9143e4501f9f212cb6813b3815edbc7013d6a3f0f1087' s = Script.from_hex(script_hex) sc = classify_output_script(s, Bitcoin) assert isinstance(sc, P2SH_Address) suffix = push_item(b'foobar') + pack_byte(OP_DROP) + pack_byte(OP_NOP) s2 = Script.from_hex(script_hex + suffix.hex()) sc2 = classify_output_script(s2, Bitcoin) assert s2 != s assert isinstance(sc2, P2SH_Address)
def test_P2PKH(self): script_hex = '76a914a6dbba870185ab6689f386a40522ae6cb5c7b61a88ac' s = Script.from_hex(script_hex) sc = classify_output_script(s, Bitcoin) assert isinstance(sc, P2PKH_Address) prefix = push_item(b'foobar') + pack_byte(OP_DROP) + pack_byte(OP_NOP) s2 = Script.from_hex(prefix.hex() + script_hex) sc2 = classify_output_script(s2, Bitcoin) assert s2 != s assert isinstance(sc2, P2PKH_Address)
def test_P2PK(self): script_hex = '210363f75554e05e05a04551e59d78d78965ec6789f42199f7cbaa9fa4bd2df0a4b4ac' s = Script.from_hex(script_hex) sc = classify_output_script(s, Bitcoin) assert isinstance(sc, P2PK_Output) assert (sc.public_key.to_hex() == '0363f75554e05e05a04551e59d78d78965ec6789f42199f7cbaa9fa4bd2df0a4b4') suffix = push_item(b'foo') + push_item(b'bar') + pack_byte(OP_2DROP) s2 = Script.from_hex(script_hex + suffix.hex()) sc2 = classify_output_script(s2, Bitcoin) assert sc2.public_key == sc.public_key assert s2 != s assert isinstance(sc2, P2PK_Output)
def _test_op_return(self, old=False): prefix = b'' if old else pack_byte(OP_0) s = Script(prefix + pack_byte(OP_RETURN)) sc = classify_output_script(s, Bitcoin) assert isinstance(sc, OP_RETURN_Output) s = Script(prefix + pack_byte(OP_RETURN) + push_item(b'BitcoinSV')) sc = classify_output_script(s, Bitcoin) assert isinstance(sc, OP_RETURN_Output) # Truncated OP_RETURN script s = Script(prefix + pack_byte(OP_RETURN) + pack_byte(1)) sc = classify_output_script(s, Bitcoin) assert isinstance(sc, OP_RETURN_Output)
def test_P2MultiSig(self): script_hex = ('5221022812701688bc76ef3610b46c8e97f4b385241d5ed6eab6269b8af5f9bfd5a89c210' '3fa0879c543ac97f34daffdaeed808f3500811aa5070e4a1f7e2daed3dd22ef2052ae') s = Script.from_hex(script_hex) sc = classify_output_script(s, Bitcoin) assert isinstance(sc, P2MultiSig_Output) assert len(sc.public_keys) == 2 assert sc.threshold == 2 # Confirm suffix fails to match s = Script.from_hex(script_hex + 'a0') assert isinstance(classify_output_script(s, Bitcoin), Unknown_Output) # Confirm prefix fails to match s = Script.from_hex('a0' + script_hex) assert isinstance(classify_output_script(s, Bitcoin), Unknown_Output)
def string_to_script_template(text: str) -> ScriptTemplate: # raises bip276.ChecksumMismatchError if text.startswith(PREFIX_SCRIPT): prefix, version, network, data = bip276_decode(text, Net.BIP276_VERSION) assert network == Net.BIP276_VERSION, "incompatible network" return classify_output_script(Script(data), Net.COIN) return Address.from_string(text, Net.COIN)
def test_to_script(self): address = P2SH_Address( bytes.fromhex('ca9f1c4998bf46f66af34d949d8a8f189b6675b5'), Bitcoin) S = address.to_script() assert isinstance(S, Script) assert S == address.to_script_bytes() assert isinstance(classify_output_script(S, Bitcoin), P2SH_Address)
def test_to_script(self): address = P2PKH_Address( bytes.fromhex('d63cc1e3b6009e31d03bd5f8046cbe0f7e37e8c0'), Bitcoin) S = address.to_script() assert isinstance(S, Script) assert S == address.to_script_bytes() assert isinstance(classify_output_script(S, Bitcoin), P2PKH_Address)
def test_to_script(self): pubkey_hex = '0363f75554e05e05a04551e59d78d78965ec6789f42199f7cbaa9fa4bd2df0a4b4' pubkey = PublicKey.from_hex(pubkey_hex) output = P2PK_Output(pubkey, Bitcoin) S = output.to_script() assert isinstance(S, Script) assert S == output.to_script_bytes() assert isinstance(classify_output_script(S, Bitcoin), P2PK_Output)
def test_unknown(self): # Modified final pubkey byte; not a curve point script_hex = '210363f75554e05e05a04551e59d78d78965ec6789f42199f7cbaa9fa4bd2df0a4b3ac' s = Script.from_hex(script_hex) sc = classify_output_script(s, Bitcoin) assert isinstance(sc, Unknown_Output) # Truncated script script_hex = '210363f7' s = Script.from_hex(script_hex) sc = classify_output_script(s, Bitcoin) assert isinstance(sc, Unknown_Output) # Unknown script script_hex = pack_byte(OP_1).hex() s = Script.from_hex(script_hex) sc = classify_output_script(s, Bitcoin) assert isinstance(sc, Unknown_Output)
def to_public_key(self): '''Returns a PublicKey instance or an Address instance.''' kind = self.kind() if kind in {0x02, 0x03, 0x04}: return PublicKey.from_bytes(self.raw) if kind == 0xff: return self._bip32_public_key() if kind == 0xfe: return self._old_keystore_public_key() assert kind == 0xfd result = classify_output_script(Script(self.raw[1:]), Net.COIN) assert isinstance(result, Address) return result
def classify_tx_output(tx_output: TxOutput) -> ScriptTemplate: # This returns a P2PKH_Address, P2SH_Address, P2PK_Output, OP_RETURN_Output, # P2MultiSig_Output or Unknown_Output return classify_output_script(tx_output.script_pubkey, Net.COIN)
def address(self): return classify_output_script(self.script)
def _script_to_address(script_hex): result = classify_output_script(Script.from_hex(script_hex)) assert isinstance(result, Address) return result
def __init__(self, main_window: 'ElectrumWindow', row: InvoiceRow) -> None: super().__init__(main_window, _("Invoice")) self.setMinimumWidth(400) self._main_window = weakref.proxy(main_window) self._pr = pr = PaymentRequest.from_json(row.invoice_data) state = row.flags & PaymentFlag.STATE_MASK if state & PaymentFlag.UNPAID and has_expired(row.date_expires): state = PaymentFlag.EXPIRED total_amount = 0 for output in pr.outputs: total_amount += output.amount vbox = QVBoxLayout(self) form = FormSectionWidget(minimum_label_width=120) form.add_row(_('Type'), QLabel(_("BIP270"))) form.add_row(_("State"), QLabel(pr_tooltips.get(state, _("Unknown")))) form.add_row( _('Amount'), QLabel( app_state.format_amount(output.amount) + " " + app_state.base_unit())) form.add_row(_('Memo'), QLabel(row.description)) form.add_row(_('Date Created'), QLabel(format_time(pr.creation_timestamp, _("Unknown")))) form.add_row(_('Date Received'), QLabel(format_time(row.date_created, _("Unknown")))) if row.date_expires: form.add_row(_('Date Expires'), QLabel(format_time(row.date_expires, _("Unknown")))) vbox.addWidget(form) self._table = table = ButtonsTableWidget() table.setSelectionBehavior(QAbstractItemView.SelectRows) table.setSelectionMode(QAbstractItemView.SingleSelection) vh = table.verticalHeader() vh.setSectionResizeMode(QHeaderView.ResizeToContents) vh.hide() table.setColumnCount(3) table.setContextMenuPolicy(Qt.CustomContextMenu) table.customContextMenuRequested.connect(self._on_table_menu) table.setHorizontalHeaderLabels(self._table_column_names) table.setRowCount(len(pr.outputs)) # table.addButton("icons8-copy-to-clipboard-32.png", f, # _("Copy all listed destinations to the clipboard")) # table.addButton("icons8-save-as-32-windows.png", f, # _("Save the listed destinations to a file")) hh = table.horizontalHeader() hh.setStretchLastSection(True) for row, output in enumerate(pr.outputs): label = QLabel( app_state.format_amount(output.amount) + " " + app_state.base_unit()) table.setCellWidget(row, 0, label) table.setCellWidget(row, 1, QLabel(output.description)) kind = classify_output_script(output.script, Net.COIN) text = script_to_display_text(output.script, kind) table.setCellWidget(row, 2, QLabel(text)) vbox.addWidget(table, 1) def do_export(): fn = self._main_window.getSaveFileName(_("Export invoice to file"), "*.bip270.json") if not fn: return with open(fn, 'w') as f: data = f.write(row.invoice_data) self._main_window.show_message(_('Invoice saved as' + ' ' + fn)) exportButton = EnterButton(_('Export'), do_export) def do_delete(): if self.question( _('Are you sure you want to delete this invoice?'), title=_("Delete invoice"), icon=QMessageBox.Warning): self._main_window._send_view._invoice_list._delete_invoice( row.invoice_id) self.close() deleteButton = EnterButton(_('Delete'), do_delete) vbox.addLayout(Buttons(exportButton, deleteButton, CloseButton(self)))