Bitcoin untuk pemula, Bagian 3: API BitCoinJ

Untuk pengembang Java, BitCoinJ adalah titik masuk untuk mengembangkan aplikasi yang berinteraksi dengan jaringan Bitcoin. Dalam artikel terakhir dalam seri tiga bagian ini, Dirk Merkel membantu Anda menyiapkan BitCoinJ di lingkungan pengembangan Eclipse, kemudian menjelaskan beberapa latihan singkat yang akan membiasakan Anda dengan implementasi ringan dari protokol transaksi Bitcoin ini.

Angsuran sebelumnya dalam seri tiga bagian ini telah memperkenalkan kerangka kerja konseptual dan teknologi Bitcoin, mata uang virtual dan jaringan peer-to-peer. Artikel ini, tutorial pengantar BitCoinJ API, mengasumsikan bahwa Anda sudah familiar dengan alamat, transaksi, blok, dan rantai blok Bitcoin.

BitCoinJ adalah implementasi Java open source dari protokol Bitcoin. Dengan demikian, ini adalah alat yang berguna untuk dimiliki jika Anda ingin menulis aplikasi Java yang berinteraksi dengan jaringan Bitcoin. Untuk menjelajahi BitCoinJ API, kami akan membuat berbagai contoh aplikasi yang menggambarkan langkah-langkah pemrograman yang diperlukan untuk membangun aplikasi Bitcoin yang lebih kompleks di Java. Setelah menggunakan Maven untuk membangun dan menyiapkan proyek di Eclipse IDE, kami akan berlatih membuat alamat Bitcoin, menyimpannya di dompet, dan menyimpan dompet ke disk. Kami kemudian akan membuat koneksi ke jaringan pengujian Bitcoin dan mengambil blok genesisnya. Terakhir, kami akan mengikat kode sampel kami sejauh ini dengan mengirimkan beberapa Bitcoin ke alamat di jaringan pengujian.

Tentang BitCoinJ

BitCoinJ adalah implementasi Java dari protokol Bitcoin. Ditulis oleh Mike Hearn, BitCoinJ bukanlah implementasi penuh dari klien Bitcoin asli, tetapi versi yang lebih ringan dan dapat diakses. Meskipun cukup solid untuk dipelajari, BitCoinJ masih dalam pengembangan (saat ini di v.0.3) dan tidak boleh digunakan untuk memindahkan sejumlah besar Bitcoin.

Mulailah dengan BitCoinJ

BitCoinJ dihosting oleh Google Code dalam repositori Subversion, dan dapat diperiksa secara anonim. Setelah Anda memeriksa bagasi proyek BitCoinJ, Anda akan dapat dengan mudah memperbaruinya. Namun, Anda tidak akan dapat melakukan perubahan apa pun.

Anda dapat menggunakan klien Subversion yang dibangun ke dalam IDE favorit Anda atau cukup periksa proyek dari baris perintah, seperti yang saya lakukan:

Setelah Anda memiliki kodenya, Anda akan mengkompilasinya dengan Maven, sistem build BitCoinJ. Maven mengambil pendekatan siklus hidup untuk membangun proyek dan sangat dapat dikembangkan dengan banyak plugin inti dan pihak ketiga. Apa yang dilakukan Maven dengan sangat baik adalah mengelola dependensi. Jika Anda melihat file pom.xml Maven di direktori root BitCoinJ, Anda akan melihat bahwa file ini hanya menggunakan sedikit dependensi; ini termasuk JUnit dan EasyMock untuk pengujian unit, SLF4J untuk logging, dan Bouncy Castle Crypto API untuk operasi kriptografi seperti hashing dan penandatanganan.

Dari baris perintah, jalankan mvn clean packagedan Maven akan mengambil dependensi ini dan lainnya, mengkompilasi proyek, menjalankan unit test suite, dan mengemas kode yang telah dikompilasi ke dalam file JAR snapshot. Seperti yang ditunjukkan pada Gambar 2, Maven pertama-tama menjalankan siklus proses bersih untuk menyingkirkan artefak apa pun dari build sebelumnya. Itu kemudian mengeksekusi fase siklus hidup default hingga dan termasuk fase paket.

Maven memiliki beberapa trik berguna lainnya. Pertama, mengeksekusi mvn site:sitemembangun dokumentasi BitCoinJ, termasuk halaman tentang dependensi, pelacakan masalah, milis, lisensi, tim pengembangan, repositori sumber, dan lainnya. Halaman-halaman ini cenderung informatif tetapi mendasar. Pelaksana mvn javadoc:javadocmenghasilkan dokumentasi proyek, yang akan berguna ketika kita mulai menggunakan API BitCoinJ.

Dokumentasi mengungkapkan bahwa API dibagi menjadi empat paket:

  • Penemuan berhubungan dengan penemuan / komunikasi jaringan peer-to-peer.
  • Penyimpanan berisi struktur data untuk menyimpan blok dan rantai blok.
  • Contohnya termasuk beberapa aplikasi sederhana berdasarkan BitCoinJ (ini menginspirasi contoh saya sendiri untuk artikel ini).
  • Core berisi mayoritas kelas dan fungsionalitas BitCoinJ, termasuk kelas untuk berkomunikasi dengan node rekan, mengunduh rantai blok, dan mengirim dan menerima transaksi.

Siapkan proyek contoh di Eclipse

Kami akan mengembangkan kode contoh untuk artikel ini di Eclipse, menggunakan Maven untuk mengelola BitCoinJ sebagai dependensi. Untungnya, BitCoinJ memiliki lingkungan integrasi berkelanjutan yang membangun proyek, mengumpulkan dan melaporkan berbagai artefak, dan menyimpan snapshot JAR ke dalam repositori Maven berbasis Nexus milik proyek.

Gambar 3 menunjukkan dialog pembuatan proyek Eclipse yang dihasilkan dari pembuatan proyek Maven baru dan pemilihan arketipe "quickstart", yang menghasilkan proyek Maven dasar. Kode saya untuk proyek ini ada dalam paket bernama com.waferthin.bitcoinj, yang menghasilkan 0.0.1-SNAPSHOT dengan build Maven.

Mengklik Selesai memerintahkan wizard untuk membuat proyek, yang berarti menjatuhkan kelas utama "Hello World" ke dalam direktori proyek - dinamai src/main/java/com/waferthin/bitcoinjdalam kasus saya.

Akhirnya, kita perlu memberi tahu Maven bahwa proyek tersebut bergantung pada snapshot BitCoinJ, seperti yang ditunjukkan pada Listing 1. Saya mengedit file pom.xml yang dihasilkan wizard milik Maven untuk menyatakan lokasi dan nama repositori Nexus BitCoinJ (baris 18 hingga 28) dan mengatur versi yang akan diandalkan untuk build (baris 39 hingga 45):

Daftar 1. Maven pom.xm untuk proyek BitCoinJ

001| 002| 4.0.0 003| 004| com.waferthin.bitcoinj.explored 005| bitcoinj-explored 006| 0.0.1-SNAPSHOT 007| jar 008| 009| bitcoinj-explored 010| //maven.apache.org 011| 012|  013| UTF-8 014|  015| 016|  017|  018|  019| bitcoinj-release 020|  021| 022|//nexus.bitcoinj.org/content/repositories/releases 023|  024|  025| bitcoinj-snapshot 026|  027| //nexus.bitcoinj.org/content/repositories/snapshots 028|  029|  030| 031|  032|  033| junit 034| junit 035| 3.8.1 036| test 037|  038| 039|  040|  041| com.google 042| bitcoinj 043| 0.3-SNAPSHOT 044| compile 045|  046|  047|

Itu saja yang ada untuk itu. Di bagian selanjutnya kita akan mengimpor kelas BitCoinJ ke dalam kode kita dan membangun proyek BitCoinJ dengan Maven, semuanya tanpa harus menyalin file JAR yang sebenarnya.

Membuat alamat Bitcoin

Untuk mengirim atau menerima Bitcoin, Anda memerlukan alamat. Alamat berasal dari bagian publik dari pasangan kunci kriptografi publik-swasta (lihat "Bitcoin untuk pemula, Bagian 2: Bitcoin sebagai teknologi dan jaringan"). Jenis kriptografi yang digunakan oleh Bitcoin disebut kriptografi kurva eliptik (ECC). Kriptografi kunci publik yang kebanyakan kita ketahui didasarkan pada kesulitan menemukan faktor prima dari bilangan bulat besar. Sebaliknya, ECC didasarkan pada kesulitan menemukan logaritma diskrit dari kurva elips. (Menjelaskan hal ini secara lebih rinci tidak hanya akan membawa kita ke lubang kelinci aljabar yang lebih tinggi, tetapi juga akan dengan cepat melebihi matematika perguruan tinggi saya. Untungnya, kita tidak perlu mengetahui lebih banyak untuk menggunakan ECKeykelas BitCoinJ untuk mewakili dan menghasilkan kunci berpasangan.)

Sejalan 20 dari Listing 2, kami membuat pasangan kunci kurva elips baru dengan membuat instance objek bertipe ECKey. Perhatikan bahwa toString()metode default kelas ditimpa untuk mengembalikan kunci publik dan privat dalam notasi hex, yang digunakan pada baris 23.

Kode 2. Membuat pasangan kunci kurva elips dengan ECKey

001|package com.waferthin.bitcoinj; 002| 003|import com.google.bitcoin.core.ECKey; 004|import com.google.bitcoin.core.NetworkParameters; 005|import com.google.bitcoin.core.Address; 006| 007|public class CreateAddress  008

You might recall that the public part of a Bitcoin key pair should be an address. But the public part of the key generated by the above code will initially look nothing like the addresses the Bitcoin client displays in its UI. The address form we're used to seeing in a Bitcoin transaction is derived by repeated hash operations to the public key. This form includes a flag that indicates which of the two Bitcoin networks the key belongs to -- Bitcoin's production network or its test network. (See the Bitcoin wiki page for a more detailed description of the algorithmic creation of Bitcoin key pairs.)

Differentiating Bitcoin networks

Currently there are two Bitcoin networks, one for production and one that is used for development. Both networks have their own genesis block and subsequent block chain. Later in this article, we'll use the Bitcoin testnet to execute a Bitcoin transaction. For now, you only need to know that the networks are differentiated by pre-pending a single byte to the input to one of the cryptographic hashes in the ECC algorithm: 0x6f indicates the production network and 0x00 the test one.

We don't need to apply the sequence of cryptographic hashes ourselves because the ECKey class provides the same functionality with the toAddress() method. After invoking that method and passing in the type of network via a NetworkParameters object (see line 26 in Listing 2), the toAddress() method returns an Address object. That object's toString() method will yield a true Bitcoin address. After compiling and executing the class I get the following address for Bitcoin's test network:

mpJ9UDd4qtNhMiGefK8NM1V5PMq9jMb7ck

Testnet addresses typically start with m or n, whereas production addresses start with 1. Try executing the same code on your own machine and you will get a different, unique address.

Wallets and keys

If you participate in the Bitcoin economy, you likely keep all of your riches in your wallet. The wallet is nothing more than a local data file that contains serialized objects representing all of your Bitcoin transactions and a cache of unused addresses. The sum of your incoming and outgoing transaction amounts is the amount of Bitcoins in your wallet. In this section we'll use BitCoinJ's Wallet object to create a wallet data file, populate it with five addresses, and save it to disk.

The Wallet class implements the Serializable interface to enable us to persist it to disk or some other more permanent storage medium. Specifically, methods loadFromFile(File) and the corresponding saveToFile(File) read and write wallet files. We'll be using loadFromFile(File) to write a newly created wallet object to a file.

Note that BitCoinJ wallet files are not compatible with wallet files created by the official Bitcoin client.

Creating and storing keys

The Walletkelas memiliki anggota masyarakat bernama keychainyang merupakan ArrayListtipe ECKey, yang digunakan untuk menyimpan semua pasangan kunci EC dalam dompet. The addKey(ECKey)metode yang digunakan untuk menambah pasangan kunci, tapi saat ini belum ada metode untuk menghapusnya. Ini masuk akal karena seharusnya tidak mudah bagi pengguna atau program untuk menghapus kunci privat: kunci privat diperlukan untuk mengakses dana yang dikirim melalui kunci publik yang sesuai. Tanpa pasangan kunci di dompet atau dicadangkan di suatu tempat, dana yang dikirim akan hilang selamanya.