Ihr werdet Euch bestimmt wundern, warum wir einen bestehenden Zeitstempel erweitern (müssen) und es nicht gleich in einem Rutsch komplett machen. Der Grund dafür ist ganz einfach und hat mit Arbeitsweise der Bitcoin-Blockchain zu tun: die Blockchain bietet keine direkte Möglichkeit, auf eine einzelne Transaktion zuzugreifen.
Wenn ich einen der zahlreichen Bitcoin (Testnetz-) Blockexplorer benutze kann ich doch einfach den Hash der Transaktion eingeben und erhalte direkt die Transaktion auf den Bildschirm… aber das liegt daran, dass diese Systeme intern eine komplette Datenbank mit allen Transaktionen vorliegen haben. Das setzt voraus, das die komplette Blockchain mit allen Rohdaten auf der eigenen Festplatte liegen muss und das können schon mal 160 GB oder mehr sein. Um „mal eben“ einen Timestamp zu überprüfen wird wohl kein Anwender freiwillig diese Datenmenge herunterladen.
Natürlich steht mir der im Programm „BitcoinJ Erzeuge einen Timestamp“ vorgeschlagene Weg der manuellen Abfrage einer Transaktion (Online Bitcoin Explorer) immer zur Verfügung, aber wir möchten das Ganze doch mit Java-Mitteln erledigen. Die Einzige externe Zugriffsmöglichkeit auf die Daten einer Transaktion besteht darin, zuerst den Block ausfindig zu machen, in dem sich die fragliche Transaktion befindet und genau das erledigt unser kleines Erweiterungs-Programm. Bitte beachtet dabei, das Ihr zwischen der Erstellung und der Erweiterung des Timestamps bis zu 30 Minuten warten müsst, denn zuerst muss der Block ja die Transaktion aufgenommen und ein Miner den Block in die Blockchain eingereiht haben. Diese Wartezeit ist genau der Grund für die Zweiteilung des Programms (Erstellung und Erweiterung), denn so könnt Ihr viele Timestamps hintereinander erledigen und später dann die Timestamps erweitern.
Die Benutzung ist wieder sehr einfach gehalten zuerst startet Ihr das Programm und wählt „starte das Wallet“:
Eine JProgressBar informiert Euch über die Aktualisierung des Wallets:
Mit dem Klick auf „waehlen Sie eine Datei…“ sucht Ihr die Originaldatei auf der Festplatte („neben“ der Datei muss die Textdatei mit dem Timestamp liegen, die Ihr im Beispiel BitcoinJ Erzeuge einen Timestamp erzeugt habt).
Das Programm sucht die Transaktion in einem Block und schreibt die Blockadresse („Block Hash“) in eine neue Textdatei „neben“ der Originaldatei. Diese Datei hat am Ende den Dateinamen „.timestamp_extended.txt“:
Sollte die Transaktion noch nicht in einem Block verarbeitet worden sein gibt das Programm diese Warnung aus. Bitte wartet bis zu 30 Minuten, dann sollte die Transaktion auch gefunden werden:
So sieht die erweiterte Timestamp-Datei aus (in den Zeilen 2 und 3 stehen nun der Blockhash und die Blocknummer (Block Height); diese Informationen werden zusätzlich unterhalb der bisherigen Datei gezeigt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
406952a7ec2da89814ab1b635b6bad3e5fc46affdfd7c4deaa301973e7939aa0 0000000000000004e14452831e1c3a3bc58e906e70f44e8f2969b4fbd85c2071 1670699 3e383e47ec7a5434c918eceef3c1443931d5ed85061629378d3299710e649941 C:\Users\admi\Documents\java-crypto_bplaced_net.pdf 61455 21.03.2020 12:52:33 ********************************************************************************** ******* do not edit above lines | bitte die oberen Zeilen nicht veraendern ******* ********************************************************************************** This Timestamp was created with / Dieser Zeitstempel wurde generiert mit http://java-crypto.bplaced.net/bitcoinj-erzeuge-einen-timestamp/ Sourcecode : https://github.com/java-crypto/BitcoinJTimestamp Dateiname : C:\Users\xxx\Documents\java-crypto_bplaced_net.pdf Dateigroesse : 61455 (Bytes) Dateidatum/Zeit : 21.03.2020 12:07:09.981 (zuletzt modifiziert) Timestamp-Datei : C:\Users\xxx\Documents\java-crypto_bplaced_net.pdf.timestamp.txt Hashwert SHA256 : 3e383e47ec7a5434c918eceef3c1443931d5ed85061629378d3299710e649941 Datum Timestamp : 21.03.2020 12:52:33 TransaktionsId : 406952a7ec2da89814ab1b635b6bad3e5fc46affdfd7c4deaa301973e7939aa0 Network-ID : org.bitcoin.test ********************************************************************************** Block Hash : 0000000000000004e14452831e1c3a3bc58e906e70f44e8f2969b4fbd85c2071 Block Height : 1670699 ********************************************************************************** |
Im Echteinsatz könntet Ihr nun die Originaldatei und die erweiterte Timestamp-Datei an einen Dritten geben und der könnte die Daten überprüfen – z.B. mit dem Beispiel „BitcoinJ Überprüfe einen Timestamp„.
Die Sourcecodes findet Ihr am Ende des Artikels.
Alle Quellcodes zu BitcoinJ Timestamps & OP_RETURN findet Ihr zum Download in meinem GitHub-Repository BitcoinJTimestamp, welches Ihr über diesen Link erreicht: https://github.com/java-crypto/BitcoinJTimestamp. Alle Programme sind unter Java 11 lauffähig (vermutlich auch unter Java 8) und wurden mit intelliJ IDEA entwickelt, welches für dieses Programm aber nicht notwendig ist.
Zur Nutzung der Programme benötigt Ihr diverse Bibliotheken – ladet Euch diese aus dem separaten GitHub-Archiv (https://github.com/java-crypto/BitcoinJ_Libraries) herunter und bindet Sie über Eure Entwicklungsumgebung ein.
Noch ein Wort zum Thema „Lizenz“: Das Programm steht unter unterschiedlichen Lizenzen, die Ihr bitte beachten solltet. Die von mir erstellten Beispiele selber stehen unter der „Unlicense“-Lizenz, allerdings werden zur Laufzeit diverse Bibliotheken eingebunden, welche zum Teil ganz eigene Lizenzen mitbringen. Darauf kann ich in meinen Lizenzhinweisen nicht hinweisen.
Letzte Bearbeitung: 22.03.2020
Hier der Sourcecode des Programms und der Form; den Quellcode der Klasse RedirectedFrame.java findet Ihr in meinem GitHub-Repository:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 |
/* * Herkunft/Origin: http://javacrypto.bplaced.net/ * Programmierer/Programmer: Michael Fehr * Copyright/Copyright: Michael Fehr * Lizenttext/Licence: verschiedene Lizenzen / several licenses * getestet mit/tested with: Java Runtime Environment 11.0.5 x64 * verwendete IDE/used IDE: intelliJ IDEA 2019.3.1 * Datum/Date (dd.mm.jjjj): 21.03.2020 * Funktion: Erweitert die Timestamp-Datei um den Block-Hash und die Block Height * Function: appends the timestamp-file with block-hash and block-height * * Sicherheitshinweis/Security notice * Die Programmroutinen dienen nur der Darstellung und haben keinen Anspruch auf eine korrekte Funktion, * insbesondere mit Blick auf die Sicherheit ! * Prüfen Sie die Sicherheit bevor das Programm in der echten Welt eingesetzt wird. * The program routines just show the function but please be aware of the security part - * check yourself before using in the real world ! * * Sie benötigen diverse Bibliotheken (alle im Github-Archiv im Unterordner "libs") * You need a lot of libraries (see my Github-repository in subfolder "libs") * verwendete BitcoinJ-Bibliothek / used BitcoinJ Library: bitcoinj-core-0.15.6.jar * my Github-Repository: https://github.com/java-crypto/BitcoinJ * libs in my Github-Repo: https://github.com/java-crypto/BitcoinJ_Libraries * */ import org.bitcoinj.core.*; import org.bitcoinj.kits.WalletAppKit; import org.bitcoinj.params.MainNetParams; import org.bitcoinj.params.RegTestParams; import org.bitcoinj.params.TestNet3Params; import org.bitcoinj.store.BlockStore; import org.bitcoinj.store.BlockStoreException; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; public class BitcoinJExtendATimestamp { private WalletAppKit kit; boolean kitIsRunning = false; private NetworkParameters netParams; private LocalDateTime localDateTimeStart; private LocalDateTime localDateTimeEnd; private String filenameWallet = "TimestampOwn"; private String filenameTimestampAppend = ".timestamp.txt"; private String filenameTimestampExtendedAppend = ".timestamp_extended.txt"; private String filenameTimestamp; private Coin balance; private Sha256Hash sha256Hash; private Color colorStatus; public BitcoinJExtendATimestamp() throws IOException, InterruptedException { // choose network type (MAIN, TEST or REG) //String networkType = "MAIN"; String networkType = "TEST"; //String networkType = "REG"; switch (networkType) { case "MAIN": { netParams = MainNetParams.get(); filenameWallet = filenameWallet + "_Mainnet"; break; } case "TEST": { netParams = TestNet3Params.get(); filenameWallet = filenameWallet + "_Testnet"; break; } case "REG": { netParams = RegTestParams.get(); filenameWallet = filenameWallet + "_Regtest"; break; } default: { System.out.println("Es ist kein networkType angegeben, das Programm wird in 10 Sekunden beendet"); tfStatus.setText("Kein networkType angegeben, Programm endet in 10 Sekunden"); tfStatus.setBackground(Color.RED); TimeUnit.SECONDS.sleep(10); System.exit(0); } } System.out.println("Das Programm arbeitet im Netzwerk: " + netParams.getId()); System.out.println("Guten Tag, zum Start bitte den Button 'starte das wallet' druecken"); localDateTimeStart = LocalDateTime.now(); kitIsRunning = false; colorStatus = tfStatus.getBackground(); btnFileChooser.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { tfFile.setText(""); tfHash.setText(""); tfBlockHeight.setText(""); tfBlockHash.setText(""); tfProofFile.setText(""); tfTxId.setText(""); tfStatus.setText(""); tfStatus.setBackground(colorStatus); filenameTimestamp = ""; sha256Hash = null; File file = chooseFile(); try { tfFile.setText(file.toString()); } catch (NullPointerException e) { } if (tfFile.getText() != "") { filenameTimestamp = tfFile.getText(); System.out.println("Datei die mit einem Timestamp versehen werden soll: " + filenameTimestamp); try { sha256Hash = Sha256Hash.of(file); } catch (IOException e) { e.printStackTrace(); } tfHash.setText(String.valueOf(sha256Hash)); // perform the next steps System.out.println("\nInformationen im OP_RETURN-Bereich der Transaktion werden gesucht:"); // wir prüfen ob die proof-datei existiert String filenameTimestamp = tfFile.getText() + filenameTimestampAppend; tfProofFile.setText(filenameTimestamp); File fileTimestamp = new File(filenameTimestamp); System.out.println("Die Timestamp-Datei " + filenameTimestamp + " ist vorhanden: " + fileTimestamp.exists()); if (!fileTimestamp.exists()) { System.out.println("Die Timestamp-Datei ist nicht vorhanden und kann nicht erweitert werden"); return; } if (!fileTimestamp.canRead() || !fileTimestamp.isFile()) { return; } BufferedReader in = null; String zeile = ""; try { in = new BufferedReader(new FileReader(filenameTimestamp)); zeile = null; // nur die erste zeile wird gelesen zeile = in.readLine(); } catch (IOException e) { e.printStackTrace(); } finally { if (in != null) try { in.close(); } catch (IOException e) { } } try { in.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println(("TxId in der Datei: " + zeile)); String TxId = zeile; tfTxId.setText(TxId); // einlesen aller eigenen tx aus dem wallet und sortierung ArrayList<Transaction> txList = new ArrayList(kit.wallet().getTransactions(true)); txList.sort((tx1, tx2) -> { return tx2.getUpdateTime().compareTo(tx1.getUpdateTime()); }); boolean txFund = false; int block = 0; int blockDepth = 0; for (int i = 0; i < txList.size(); i++) { Transaction tx = txList.get(i); String TxTxId = tx.getTxId().toString(); if (TxTxId.equals(TxId)) { // System.out.println("* * * Fund in Tx Nr. " + i); txFund = true; try { block = tx.getConfidence().getAppearedAtChainHeight(); } catch (IllegalStateException e) { System.out.println("Exception block " + e); System.out.println("Die Transaktion wurde gefunden, ist aber noch nicht in einem Block vorhanden"); tfStatus.setText("Die Transaktion wurde noch nicht in einem Block gefunden"); tfStatus.setBackground(Color.YELLOW); txFund = false; break; } tfBlockHeight.setText(String.valueOf(block)); try { blockDepth = tx.getConfidence().getDepthInBlocks(); } catch (Exception e) { //System.out.println("Exception depth " + e); } System.out.println("Die Transaktion wurde gefunden und die erweiterte Timestamp-Datei wurde erzeugt"); tfStatus.setText("Transaktion gefunden und die erweiterte Timestamp-Datei erzeugt"); tfStatus.setBackground(Color.GREEN); break; // schleife beenden } else { txFund = false; System.out.println("Die Transaktion wurde nicht gefunden"); tfStatus.setText("Die Transaktion wurde nicht gefunden"); } } if (txFund == true) { int heightToFind = Integer.parseInt(tfBlockHeight.getText()); // wir benötigen den blockhash für eine spätere direkte suche // System.out.println("\n*** Suche den Blockhash ***"); BlockChain chain = kit.chain(); BlockStore bs = chain.getBlockStore(); Peer peer = kit.peerGroup().getDownloadPeer(); // Get last block StoredBlock current = null; try { current = bs.getChainHead(); } catch (BlockStoreException e) { e.printStackTrace(); } //System.out.println("*** current = last block:\n" + current.toString() + "\n"); //System.out.println("*** Last Block (height) getHeight: " + current.getHeight() + "\n"); //System.out.println("Wir arbeiten im folgenden Netz:" + kit.params().getId()); int nr = 1; // Loop until you reach the genesis block int heightStart = current.getHeight(); String heightToFindHash = ""; //System.out.println("* * * heightStart: " + heightStart); while (current.getHeight() > 1) { //System.out.println("** INT: " + nr); if ((1) <= current.getHeight() && current.getHeight() <= heightStart) { // 28.02.2020 22:50 //System.out.println("* current height:\n" + current.getHeight()); Block b = null; try { b = peer.getBlock(current.getHeader().getHash()).get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } //System.out.println("* Block:\n" + b); int blockHeight = current.getHeight(); if (blockHeight == heightToFind) { //System.out.println("Der Block " + blockHeight + " wurde gefunden"); heightToFindHash = current.getHeader().getHashAsString(); tfBlockHash.setText(heightToFindHash); //System.out.println("Der Block " + blockHeight + " hat diesen Hashwert:\n" + heightToFindHash); break; } } try { current = current.getPrev(bs); } catch (BlockStoreException e) { e.printStackTrace(); } //System.out.println("** current nach getPrev(bs):\n" + current.toString()); nr++; //if (nr == 5) System.exit(0); } // schreiben der erweiterte timestamp-datei String filenameExtendedTimestamp = filenameTimestamp.replace(filenameTimestampAppend, filenameTimestampExtendedAppend); System.out.println("Speicherung des erweiterten Timestamp in die Datei:\n" + filenameExtendedTimestamp); // extended proof schreiben BufferedWriter writer = null; try { writer = new BufferedWriter(new FileWriter(filenameExtendedTimestamp)); } catch (IOException e) { e.printStackTrace(); } // timestamp lesen und in erweiterte timstamp-datei schreiben BufferedReader in2 = null; int lineRead = 0; // read and write first line = txid // write lines 2 + 3 for blockhash and blockheigth // read and write other lines in2 = null; String readZeile = ""; try { in2 = new BufferedReader(new FileReader(fileTimestamp)); readZeile = null; while ((readZeile = in2.readLine()) != null) { lineRead++; if (lineRead == 2) { try { writer.write(tfBlockHash.getText() + "\n"); writer.write(tfBlockHeight.getText() + "\n"); } catch (IOException e) { e.printStackTrace(); } } //System.out.println("Gelesene Zeile: " + readZeile); try { writer.write(readZeile + "\n"); } catch (IOException e) { e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } finally { if (in2 != null) try { in2.close(); } catch (IOException e) { } } try { writer.write("Block Hash : " + tfBlockHash.getText() + "\n"); writer.write("Block Height : " + tfBlockHeight.getText() + "\n"); writer.write("**********************************************************************************" + "\n"); writer.close(); } catch (IOException e) { e.printStackTrace(); } } } // do nothing } }); btnClose.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { //shutDownApplication(); btnFileChooser.setEnabled(false); btnClose.setEnabled(false); btnStartKit.setEnabled(false); progressBarWait.setString("Das Programm wird beendet, bitte warten ..."); tfStatus.setText("Das Programm wird beendet, bitte warten ..."); progressBarWait.setStringPainted(true); progressBarWait.setVisible(true); progressBarWait.setIndeterminate(true); Thread thread = new Thread() { public void run() { System.out.println("btnClose Thread Running"); // stop kit try { Thread.sleep(1000); // 5 seconds to end } catch (InterruptedException e) { } if (kitIsRunning) { kit.stopAsync(); kit.awaitTerminated(); } localDateTimeEnd = LocalDateTime.now(); System.out.println("Das Programm endet jetzt"); System.out.println("Datum & Zeit am Start: " + localDateTimeStart.toString()); System.out.println("Datum & Zeit am Ende : " + localDateTimeEnd.toString()); System.exit(0); } }; thread.start(); } }); btnStartKit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { // disable start button to prevent a second start btnStartKit.setEnabled(false); progressBarWait.setString("Das Wallet wird aktualisiert, bitte warten ..."); progressBarWait.setStringPainted(true); progressBarWait.setVisible(true); progressBarWait.setIndeterminate(true); if (kitIsRunning) { System.out.println("Das Wallet ist bereits gestartet"); return; } // actual date and time localDateTimeStart = LocalDateTime.now(); System.out.println("Lade ein HD-Wallet mit BitcoinJ im Bitcoin Testnet und erweitere einen Timestamp um die Block-Hash\n"); System.out.println("Das Programm benutzt das BitcoinJ WalletAppKit\n"); System.out.println("Bitte benutzen Sie Java 11 und bitcoinj-core-0.15.6.jar fuer dieses Programm\n"); Thread thread = new Thread() { public void run() { System.out.println("btn startKit Thread Running"); kit = new WalletAppKit(netParams, new File("."), filenameWallet); kit.setAutoSave(true); if (netParams == RegTestParams.get()) { kit.connectToLocalHost(); // für regtest notwendig } System.out.println("Das Wallet wurde geladen: " + filenameWallet); System.out.println("\nDas Wallet aktualisiert die Blockchain in der Datei " + filenameWallet + ".spvchain"); System.out.println("Bitte haben Sie eine bis drei Minuten Geduld"); kit.startAsync(); kit.awaitRunning(); while (!kit.isRunning()) { try { wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } } // kit is running progressBarWait.setVisible(false); progressBarWait.setIndeterminate(false); kit.wallet().allowSpendingUnconfirmedTransactions(); // nur eigene gelder, daher erlaube ich das mal System.out.println("Das aktuell verfuegbare Guthaben ist: " + kit.wallet().getBalance().toFriendlyString() + (" = ") + kit.wallet().getBalance() + " Satoshi"); tfBalance.setText(kit.wallet().getBalance().toFriendlyString() + (" = ") + kit.wallet().getBalance() + " Satoshi"); balance = kit.wallet().getBalance(); System.out.println("Aktuelle Empfangsadresse : " + kit.wallet().currentReceiveAddress()); System.out.println("Das Programm ist betriebsbereit und wartet auf den Einsatz"); kitIsRunning = true; tfStatus.setText("Das WalletAppKit laeuft"); btnFileChooser.setEnabled(true); } }; thread.start(); } }); } private File chooseFile() { JFileChooser chooser = new JFileChooser(); if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { return chooser.getSelectedFile(); } else { return null; } } private static String bytesToHex(byte[] bytes) { StringBuffer result = new StringBuffer(); for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1)); return result.toString(); } private static String getActualDateReverse() { // provides the actual date and time in this format yyyy-MM-dd_HH-mm-ss e.g. 2020-03-16_10-27-15 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"); LocalDateTime today = LocalDateTime.now(); return formatter.format(today); } public static void main(String[] args) throws IOException, InterruptedException { JFrame frame = new JFrame("Erweitere einen Timestamp fuer die Bitcoin Blockchain"); RedirectedFrame outputFrameErrors = new RedirectedFrame("Log Frame", true, false, true, "BitcoinJ_ExtendTimestamp_Logfile_" + getActualDateReverse() + ".txt", 750, 650, JFrame.DO_NOTHING_ON_CLOSE); RedirectedFrame outputFrameOutput = new RedirectedFrame("Output Frame", false, true, true, "BitcoinJ_ExtendTimestamp_Output_" + getActualDateReverse() + ".txt", 700, 600, JFrame.DO_NOTHING_ON_CLOSE); frame.setContentPane(new BitcoinJExtendATimestamp().mainPanel); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.pack(); frame.setSize(600, 450); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { //System.exit(0); // shutdownApplication(); System.out.println("Bitte drücken Sie den 'Ende des Programms' Button"); } }); frame.setVisible(true); } private JPanel mainPanel; private JButton btnFileChooser; private JTextField tfFile; private JTextField tfHash; private JTextField tfBalance; private JTextField tfBlockHeight; private JTextField tfProofFile; private JTextField tfTxId; private JTextField tfStatus; private JButton btnClose; private JButton btnStartKit; private JTextField tfBlockHash; private JProgressBar progressBarWait; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
<?xml version="1.0" encoding="UTF-8"?> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="BitcoinJExtendATimestamp"> <grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="22" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="10" left="10" bottom="10" right="10"/> <constraints> <xy x="20" y="20" width="528" height="613"/> </constraints> <properties/> <border type="none"/> <children> <component id="6a45a" class="javax.swing.JButton" binding="btnFileChooser"> <constraints> <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> </constraints> <properties> <enabled value="false"/> <text value="waehlen Sie die Datei um den Zeitstempel zu erweitern"/> </properties> </component> <component id="e0fd9" class="javax.swing.JSeparator"> <constraints> <grid row="4" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="f1a03" class="javax.swing.JTextField" binding="tfFile"> <constraints> <grid row="7" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> </properties> </component> <component id="4d2b1" class="javax.swing.JLabel"> <constraints> <grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Datei:"/> </properties> </component> <component id="93929" class="javax.swing.JSeparator"> <constraints> <grid row="8" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="6fa8" class="javax.swing.JTextField" binding="tfHash"> <constraints> <grid row="9" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> </properties> </component> <component id="14985" class="javax.swing.JLabel"> <constraints> <grid row="9" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="SHA256-Hash:"/> </properties> </component> <component id="287a2" class="javax.swing.JSeparator"> <constraints> <grid row="10" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="3e91c" class="javax.swing.JTextField" binding="tfBlockHeight"> <constraints> <grid row="11" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> </properties> </component> <component id="95cad" class="javax.swing.JLabel"> <constraints> <grid row="11" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Block Height:"/> </properties> </component> <component id="75695" class="javax.swing.JSeparator"> <constraints> <grid row="12" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="2fb3a" class="javax.swing.JTextField" binding="tfProofFile"> <constraints> <grid row="15" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> </properties> </component> <component id="6b8af" class="javax.swing.JLabel"> <constraints> <grid row="15" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Timestamp-Datei:"/> </properties> </component> <component id="c2ef" class="javax.swing.JSeparator"> <constraints> <grid row="16" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="f9349" class="javax.swing.JTextField" binding="tfTxId"> <constraints> <grid row="17" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> </properties> </component> <component id="d1077" class="javax.swing.JLabel"> <constraints> <grid row="17" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="TxId:"/> </properties> </component> <component id="49fa" class="javax.swing.JSeparator"> <constraints> <grid row="18" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="e8ac2" class="javax.swing.JTextField" binding="tfStatus"> <constraints> <grid row="19" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> </properties> </component> <component id="999d5" class="javax.swing.JLabel"> <constraints> <grid row="19" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Status:"/> </properties> </component> <component id="82258" class="javax.swing.JButton" binding="btnClose"> <constraints> <grid row="21" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Ende des Programms"/> </properties> </component> <component id="6159d" class="javax.swing.JSeparator"> <constraints> <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="7b715" class="javax.swing.JButton" binding="btnStartKit"> <constraints> <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="starte das Wallet"/> </properties> </component> <component id="4b3fc" class="javax.swing.JTextField" binding="tfBlockHash"> <constraints> <grid row="13" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> </properties> </component> <component id="7be3c" class="javax.swing.JSeparator"> <constraints> <grid row="14" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="7d86d" class="javax.swing.JLabel"> <constraints> <grid row="13" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Block Hash:"/> </properties> </component> <component id="f1b5f" class="javax.swing.JTextField" binding="tfBalance"> <constraints> <grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> </properties> </component> <component id="9855f" class="javax.swing.JLabel"> <constraints> <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Guthaben:"/> </properties> </component> <component id="386e6" class="javax.swing.JSeparator"> <constraints> <grid row="6" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="15285" class="javax.swing.JSeparator"> <constraints> <grid row="20" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="3a4f2" class="javax.swing.JProgressBar" binding="progressBarWait"> <constraints> <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"> <minimum-size width="-1" height="20"/> </grid> </constraints> <properties/> </component> </children> </grid> </form> |