Tek Satır Komut İle Bitcoin Simülasyon Ağı Çalıştırmak

Faruk Terzioğlu
5 min readOct 15, 2019

--

Bitcoin ile haberleşen uygulamalar yazmak istediğinizde, geliştirme ve test için üzerinde çalışabileceğiniz bir Bitcoin ağı kurmak zahmetli bir iş olabiliyor. Daha önce Yazılımcılar İçin Bitcoin Full Node çalıştırmayı detaylı olarak anlattım, başka bir yazımda da mainnet’e bağlanıp bitcoin ağına destek olmak için gerekenleri anlatmıştım.

Her iki yazı da gerekli adımları detaylı bir şekilde anlatmasına rağmen gerektiğinde hızlı bir çözüm sunmuyor. Onun için Docker üzerinde çalışan ve tek satır komut ile kullanacağımız bir çözüm geliştirdim. Kendi çalışmalarımda oldukça hız kazandırdı.

$ docker run --name bitcoind -d --volume /home/$USER/bitcoin_data:/root/.bitcoin -p 127.0.0.1:443:18443 farukter/bitcoind:regtest

Yukarıdaki komutu çalıştırarak (Docker kurulu bir makinede) hızlı bir şekilde simülasyon bitcoin ağı çalıştırabiliriz. Çalışan bitcoin node’una 127.0.0.1:443 adresinden rpc istekleri gönderebilirsiniz. (örnekleri aşağıda)

Çalışan Docker image’ına bir volume bağlayarak (/home/bitcoin_data gibi) verilerinizin kayıtlı kalmasını sağlayabilirsiniz. Bu sayede image’ı yeniden başlattığınızda, daha önce oluşturduğunuz adresleri kullanabilir, örnek olarak üreteceğiniz bitcoin bakiyelerini tekrar kullanabilirsiniz.

Yukarıdaki komutu incelersek;
--name ile, oluşturduğumuz container’a isim (bitcoind) veriyoruz. Bu ismi kullanarak daha sonra container’ın içine girip komutlar çalıştıracağız.

--volume ile container içerisinde bitcoin verilerinin tutulduğu dizini (/root/.bitcoin) kendi makinenizdeki bir dizine (/home/bitcoin_data) eşliyoruz. Bu sayede container durdursanız veya silseniz bile yeniden başlattığınızda verileriniz silinmeyecek.

-p parametresi ile container’daki bitcoind uygulamasının çalıştığı portu (18443) kendi makinenizdeki bir porta (443) bağlıyoruz. Ekstra güvenlik için, ‘127.0.0.1’ i belirterek de kendi makinemizdeki tüm network arayüzlerine değil de sadece belirttiğimize atanmasını sağlıyoruz.
(Detayları için tıklayın.)

Docker imajı olarak benim yüklediğimi kullanabilirsiniz: farukter/bitcoind:regtest

İsterseniz kaynak kodlarından derleyerek de çalıştırabilirsiniz;

Çalıştırdıktan sonra docker logs -f bitcoind komutu ile container’ın yazdığı loglara bakabiliriz.

Container’ı çalıştırırken parametre olarak verdiğimiz dizinde varsayılan olarak bir config dosyası oluşuyor: bitcoin.conf

Rpc istekleri yapabilmek için tanımlanan kullanıcı adı ve şifresi myuser:SomeDecentp4ssw0rd. Bu bilgileri veya diğerlerini bu dosya üzerinde değiştirip container’ını tekrar başlatırsanız yeni ayarlar geçerli olacaktır.

Simülasyon blockchain bilgisini çekmek üzere bir rpc isteği atmak için;

$ curl --user myuser:SomeDecentp4ssw0rd --data-binary '{"jsonrpc":"1.0","id":"curltext","method":"getblockchaininfo","params":[]}' -H 'content-type:text/plain;' http://127.0.0.1:443

Aynı isteği Postman’den de gönderebiliriz;

Http isteğine Basic Auth bilgileri olarak bitcoin.conf dosyasındaki kullanıcı adı ve şifresini eklemeliyiz;

Basic auth bilgileri

Yeni bir adres almak için http post isteği gönderelim;

{“jsonrpc”:”1.0",”id”:”curltext”,”method”:”getnewaddress”,”params”:[]}

Response içerisinde yeni üretilen adresi görebiliriz;

{ “result”: “2MwsHLRMeBgkvb5cwwSMNC3qVDXpt7hX7qw”}

Örnek bir transfer yapmak istersek, elimizde harcayabileceğimiz bitcoin yok. Simülasyon ağı yeni başladığı için sistemde tanımlı herhangi bir coin de yok. Onun için bir blok maden etmeliyiz ve blok ödülünü (50 Btc) az önce ürettiğimiz adrese tanımlayalım. Bunun için göndereceğimiz http isteğinin body değeri;

{“jsonrpc”:”1.0",”id”:”curltext”,”method”:”generatetoaddress”,”params”:[1, “2MwsHLRMeBgkvb5cwwSMNC3qVDXpt7hX7qw”]}

‘generatetoaddress’ metodu, parametre olarak üretmek istediğimiz blok sayısını (1) ve blok ödülünün tanımlanacağı adresi alıyor. Response içerisinde üretilen blok bilgisini görebiliriz;

{“result”: [“243522b6c868386896644c77d7708ab23aaf2c100237c2face97e6c860462b3f”]}

Blok ödülünü aldığımıza göre cüzdan bilgilerini sorgulayabiliriz;

{“jsonrpc”:”1.0",”id”:”curltext”,”method”:”getwalletinfo”,”params”:[]}

Cevap olarak aldığımız cüzdan bilgileri;

{
"result": {
"walletname": "",
"walletversion": 169900,
"balance": 0.00000000,
"unconfirmed_balance": 0.00000000,
"immature_balance": 50.00000000,
"txcount": 1,
"keypoololdest": 1571085119,
"keypoolsize": 999,
"keypoolsize_hd_internal": 1000,
"paytxfee": 0.00000000,
"hdseedid": "63***57",
"hdmasterkeyid": "63***57",
"private_keys_enabled": true
}
}

“getwalletinfo” sorgusuna aldığımız cevabı incelersek, bakiyemiz (balance) 0 fakat henüz kullanıma hazır olmayan bakiyemiz (immature_balance) ise 50Btc. Yani blok ödülü tanımlandı fakat kullanıma izin yok.

Tanımlanan blok ödülünün transferini görmek için;

{“jsonrpc”:”1.0",”id”:”curltext”,”method”:”listtransactions”,”params”:[]}

Response;

{
"result": [
{
"address": "2MwsHLRMeBgkvb5cwwSMNC3qVDXpt7hX7qw",
"category": "immature",
"amount": 50.00000000,
"label": "",
"vout": 0,
"confirmations": 1,
"generated": true,
"blockhash": "2435***2b3f",
"blockindex": 0,
"blocktime": 1571133944,
"txid": "dbec***8a8735a",
"walletconflicts": [],
"time": 1571133944,
"timereceived": 1571133944,
"bip125-replaceable": "no"
}
]
}

Listelenen bir tane transfer var, onun kategorisi de “immature”, yani harcanmak için henüz olgunlaşmış değil. Harcanabilmesi için 101 onaya sahip olması gerekiyor ve yukarı görüldüğü üzere onay sayısı (confirmation) 1.

Yeterli onay sahip olması için 100 blok daha üretelim;

{“jsonrpc”:”1.0",”id”:”curltext”,”method”:”generatetoaddress”,”params”:[100, “2MwsHLRMeBgkvb5cwwSMNC3qVDXpt7hX7qw”]}

Parametre olarak 100 verdiğimize dikkat edin. Response olarak üretilen blokların hash’leri listelenir.

Cüzdan bilgilerini tekrar çekersek;

{
"result": {
"walletname": "",
"walletversion": 169900,
"balance": 50.00000000,
"unconfirmed_balance": 0.00000000,
"immature_balance": 5000.00000000,
"txcount": 101,
"keypoololdest": 1571085119,
"keypoolsize": 999,
"keypoolsize_hd_internal": 1000,
"paytxfee": 0.00000000,
"hdseedid": "63e***757",
"hdmasterkeyid": "63***757",
"private_keys_enabled": true
}
}

Kullanılabilir bakiyemizin (balance) 50 olduğunu görebiliriz. Ürettiğimiz 100 bloğun ödülü 5000 Btc ise immature balance olarak belirtilmiş.

Artık yeni bir transfer yapabilmek için yeterli bakiyemiz, yani harcanmamış işlem çıktımız (UTXO) var. Bunu da listelemek için;

{“jsonrpc”:”1.0",”id”:”curltext”,”method”:”listunspent”,”params”:[]}

Cevap, aşağıda gördüğümüz üzere 101 onaya sahip 50 Btc’lik bir UTXO.

{
"result": [
{
"txid": "dbe***a8735a",
"vout": 0,
"address": "2MwsHLRMeBgkvb5cwwSMNC3qVDXpt7hX7qw",
"label": "",
"redeemScript": "00***5fb",
"scriptPubKey": "a9***f87",
"amount": 50.00000000,
"confirmations": 101,
"spendable": true,
"solvable": true,
"safe": true
}
]
}

Artık yeni bir transfer gönderebiliriz. Bunun için yeni bir adres üretip bu adrese bitcoin transferi gerçekleştireceğiz. Bunun örneklerini aynen yukarıda olduğu gibi http istekleri olarak gönderebiliriz. Fakat farklı bir örnek olması için, çalışan container’ın içine girip komutları cli üzerinden göndereceğim.

Daha önce ‘bitcoind’ ismini vererek çalıştırdığımız container’da interaktif (-it) olarak bir terminal bağlantısı (bash) yapmak için;

$ docker exec -it bitcoind bash

Bu arayüzden, bitcoin-cli uygulaması ile komutlar gönderebiliriz.

Yeni bir adres üretmek için; $ bitcoin-cli getnewaddress

Bu adrese yeni bir transfer göndermek için;

--

--