17 Mart 2019 Pazar

Ethereum Private POA (Proof-of-Authority) Network Kurmak

Blockchain üzerinde kurumsal uygulamalar oluşturmak için en çok kullanılan Blockchain teknolojilerinden birisi olarak Ethereum karşımıza çıkıyor. Çok kullanılmasının en önemli nedenleri programlanabilir olması, hem data hemde para’yı (Value) tutabilmesidir. 

Tek bir Ethereum adresinde ayrı ayrı birimlerden ör: USD,TL,EUR gibi düşünülebilir para tutulabiliyor, bu ise operasyonların tek bir adres üzerinden yapılabilmesinden dolayı önemli bir esneklik sağlıyor. Yani size para gönderecek birisinin adresinizi ve hangi birimden para göndereceğini bilmesi yeterli oluyor.

Kurumsal uygulamalarda Ethereum network’ü kurmak için dikkat edilmesi gereken en önemli husus consensus mekanizmasının doğru kurulmasıdır. Consensus türkçeye çevirirsek fikir birliği mekanizması demektir. Yani oluşturulan blokların nasıl oluşturulacağının ve zincire kabul edilebilmesinin şartlarının ne olacağının kararının verilmesidir.

Enerji sarfiyatının minimuma indirilmesi için consensus mekanizmasının doğru seçilmesi gerekmektedir. Private network tarafında kullanılan consensus mekanizması Proof-of-Authority olarak kurulmalıdırEthereum engine olarak Clique engine kullanılmalıdır.

Private network olarak adlandırılan bu networkler genellikle bir kurum tarafından kullanılmak için veya birden fazla kurumun aralarında kullanmak için kurdukları network’tür. Dışarıdan müdahelelere kapatılması veya sınırlandırılması gerekmektedir.

Proof-of-Authority mekanizmasında Bloklar  miner(madenci)  olarak çalışan düğüm tarafından oluşturuluyor. Networkü ayağa kaldırırken(genesis.json içerisinde) blokların Chain'e (zincire) eklenebilmesi için birden fazla node(düğüm) tarafından onaylanmasını isteyebilirsiniz.  Bu düğümlere sealer deniyor. Yani imzalayan mühürleyen anlamında. Bu mühürler olmadan blok ethererum zincirine eklenmiyor. Örnek vermek gerekirse bir kişi A bankasından işlem yapıyor ve işlemin gerçekleşmesi içinde B bankasının onayı gerekiyor. A bankasını ve B bankasını network'te sealer olarak tanımlarsanız A bankası bloğu oluşturup yollasa bile B bankası onaylamadan işlem gerçekleşmiş sayılmaz. Doğal olarak B bankası onaylayınca ilgili işlem gerçekleşir. Hatta araya birde merkez bakası gibi bir mekanizma koyup merkez bankası onaylamadan işlem  gerçekleşmez derseniz merkez bankasını da sealer olarak tanımlamalısınız.  Gördüğünüz gibi işlemler onaycılar mekanizmasından geçtikten sonra zincire ekleniyor ve gerçekleşiyor. İşin güzel tarafı bütün bunlar gerçekleşirken çok karmaşık yapıların mimarilerin içinde boğulmanıza gerek kalmıyor. Sadece bir düğümü ayağa kaldırmak ve network'e dahil etmek yeterli oluyor.

Ben kurulum yaparken resmi Ethereum implementasyonlarından Go dili ile geliştirilen Go Ethereum implementasyonunu kullandım. Go Ethereum kurulumunu https://ethereum.github.io/go-ethereum/install/ adresinden takip edebilirsiniz. 

Private network kurmak için öncelikle genesis.json dosyasını oluşturmalısınız. genesis.json dosyası düğümler ilk ayağa kalkarken ihtiyaçları olan configurasyonu vermeniz içindir. 

Genesis.json dosyasını oluşturmak için puppeth kullanabilirsiniz.  Github üzerinden puppeth https://github.com/puppeth/go-ethereum kodunu indirip build ederseniz puppeth için çalıştırılabilir dosya oluşmuş olacaktır.

Ben MACOS üzerinde çalıştığım için komutları ve kurulumları MACOS'a göre yaptım. Linux kurulumlarıda aşağı yukarı aynı şekilde yapılıyor belki windows üzerinde ufak farklılıklar olabilir. 

https://github.com/puppeth/go-ethereum  indirdiğim kodu build edip bin klasöründe ihtiyacım olan dosyaların oluştuğunu gördüm. Burada dikkat etmeniz gereken birkaç noktayı söyleyeceğim. Go implementasyonunu indirdiğim için build yaparken Go engine'e ihtiyacınız olacaktır. Öncesinde

brew install go
komutu terminalde çalıştırarak go kurulumu yapmanızı öneririm. problem çıkarsa sudo ile denemenizi öneririm.

Ben yıllarca windows üzerinde çalıştığım için MACOS üzerinde bunları yaparken biraz zorlanıyorum eğer linux üzerinde  çalışıyorsanız  bunlar sizin için çocuk oyuncağı olacaktır.

terminal üzerinde  go ethereum/build/bin klasöründe puppeth'i run ediyorum.

L52850MAC:~ osmansonmez$ cd go-ethereum/build/bin

L52850MAC:bin osmansonmez$ puppeth


Network name'i girip devam ediyorum. İsim olarak newgenesis veriyorum.




2. seçenek ile devam ediyorum.


1. seçenek ile devam ediyorum.


2. seçenek ile yani proof-of-authority seçeneği ile devam ediyorum.
ve kalan sorulara  devam ediyorum. ilk soru blok üretme süresi ne kadar olacak yani kaç saniyede bir blok üretilecek ben 5 saniye olarak veriyorum. 2. soru ise hangi hesaplar sealer olacak. Yani A bankası ve B bankasının public key'leri yani adreslerini burada gireceğiz. bunun için 2 tane ethereum adresi oluşturmamız gerekiyor. 
Adres oluşturmak için ethereum go'nun geth komutunu kullanacağız. Bunun için yeni bir terminal açmamız lazım. Terminalde geth komutları ile 2 adet ethereum hesabı oluşturacağız.



Ethereum hesabı oluşturmak için kullanacağımız komut geth account new komutudur.
komutu terminalde yazdığımızda bize hesap için şifre sormaktadır.  şifreyi girdikten sonra bize hesabı oluşturmaktadır.


ikinci adreside aynı şekilde oluşturalım ve bunları puppeth'a girelim.
Adres 1 :df6cc60abfdfdef40be53c75962b666a9febd3ef
Adres 2 :29e97a93c40d91a6cc86a03668bebecc3b989494


Tekrar puppeth ekranına dönelim.


puppeth üzerinden iki adet hesabı sealer yaptık aynı zamanda bu iki hesaba sabit olarak bir miktar ethereum yüklemesini söyledik.

Devam eden sorular başka prefunded hesaplar olacak mı bu soruya no yanıtını verdim ve benden network Id 'yi istedi. NetworkId olarak 1881' i verdim.  NetworkId değeri aynı network'e dahil olmak isteyen node'lar için önemli bir değerdir.

Daha sonra Manage existing genesis ve Export genesis configuration seçenekleri ile devam edilirse
puppeth içerisinde yer alan default klasöründe newgenesis.json dosyasının oluştuğunu göreceksiniz ve içeriği aşağıdaki gibi olacaktır.

{
  "config": {
    "chainId": 1881,
    "homesteadBlock": 1,
    "eip150Block": 2,
    "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "eip155Block": 3,
    "eip158Block": 3,
    "byzantiumBlock": 4,
    "constantinopleBlock": 5,
    "clique": {
      "period": 5,
      "epoch": 30000
    }
  },
  "nonce": "0x0",
  "timestamp": "0x5c8e4466",
  "extraData": "0x000000000000000000000000000000000000000000000000000000000000000029e97a93c40d91a6cc86a03668bebecc3b989494df6cc60abfdfdef40be53c75962b666a9febd3ef0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "gasLimit": "0x47b760",
  "difficulty": "0x1",
  "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "alloc": {
    "29e97a93c40d91a6cc86a03668bebecc3b989494": {
      "balance": "0x200000000000000000000000000000000000000000000000000000000000000"
    },
    "df6cc60abfdfdef40be53c75962b666a9febd3ef": {
      "balance": "0x200000000000000000000000000000000000000000000000000000000000000"
    }
  },
  "number": "0x0",
  "gasUsed": "0x0",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
newgenesis.json dosyasını oluşturduk. Aslında işin en büyük kısmını tamamladık sayılır. Artık 2 node'lu network'ü ayağa kaldırmak kaldı. Ben tamamını localde ayağa kaldıracağım. Dilerseniz kubernetes, docker veya openshift ortamında da ayağa kaldırabilirsiniz. Ben çok uzatmamak adına ilk etapta local'de ayağa kaldıracağım.

Öncelikle boot node ayağa kaldıracağım. Boot node nedir?
Boot node network'te bulunan node'ların birbirlerini bulabilmeleri için ayakta olan kayıt nodu'dur.
Herhangi bir transaction veya miner rolü yoktur. Esasında olay ayağa kalkan herhangi bir node'un  boot node'a ben burdayın diye haber vermesidir.

Yeni bir terminal açıp boot node'u ayağa kaldıralım.

komutlar : 

1bootnode -genkey boot.key
2- bootnode -nodekey boot.key -verbosity 9 -addr :30304

Komutları yazdıktan sonra  localde 30304 portundan boot node ayağa kalkmış olacaktır. 




bootnode bilgisini  diğer node'larla paylaşmak için enode adress bilgisini oluşturmamız gerekiyor.
enode bilgisi aşağıdaki gibi bir bilgi olmalıdır.

"enode://<your node public key>@<your node public ip>:30304"

node public key bilgisini aşağıdaki gibi oluşturmalıyız.

boot.key dosyasını vererek aşağıdaki komutu çalıştıralım.

bootnode -nodekey boot.key -writeaddress

komutu çalıştırınca bize yeni bir public key oluşturacaktır.

b19a42e8bf96953a0e365fbfbea7fba8aab55a057c086d12bd8584115e6e8b66e9a98d739e021eba2fb4b6f3eb451ffeef1287950cd596a80c88fbddc26ea6dc


yani boot node adresimiz:

enode://b19a42e8bf96953a0e365fbfbea7fba8aab55a057c086d12bd8584115e6e8b66e9a98d739e021eba2fb4b6f3eb451ffeef1287950cd596a80c88fbddc26ea6dc@127.0.0.1:30304

şeklinde olacaktır.


Şimdi Node'ları ayağa kaldıralım. Bunun için iki adet farklı klasöre ihtiyacımız olacaktır.

Node1 ve Node2 olarak 2 adet klasör açalım.

ilk komutumuz ilk node'u  yani Node1'i başlayacan konuma getirmek olacaktır. Burada daha önce oluşturduğumuz newgenesis.json dosyası gerekli olacaktır.

newgenesis.json dosyasını node1 ve node2 klasörlerine kopyalayalım. 

yeni bir terminal açalım ve node1 ve node2'yi ayarlayalım.

komut1 : geth --datadir node1/ init node1/newgenesis.json
komut2:  geth --datadir node2/ init node2/newgenesis.json

Komutları çalıştırınca node1 ve node2 klasörlerinde geth, keystore gibi klasörlerin oluştuğunu göreceksinizdir.

şimdi node'ları ayağa kaldırma zamanı:)

Hatırlıyorsanız 2 node'u  sealer olarak oluşturacaktık ve ilk başta newgenesis.json dosyasını oluştururken 2 adet ethereum hesabı oluşturmuştuk. Hesapları oluştururken 
şifre vermiştik. Şimdi node'ları ayağa kaldırırken bu hesapların bilgileri ve şifresi gerekiyor. Sebebi ise node transaction'u onaylarken vereceğimiz hesap ile onaylayacak. Yani mühürleyecek.

Hatırlıyorsanız hesapları geth komutu  ile oluşturmuştuk. hesaplar oluşunca geth'in kurulduğu ethereum klasöründe  bulunan keystore  klasöründe hesapların bilgilerinin hesap ismiyle bir dosyada tutulduğunu göreceksinizdir. 

29e97a93c40d91a6cc86a03668bebecc3b989494 hesabının keystore dosyasını node1/keystore altına,
df6cc60abfdfdef40be53c75962b666a9febd3ef hesabının keystore dosyasını node2/keystore altına kopyalayalım.

node1/ ve node2/ altında bu hesapların şifrelerini tutmak için password.txt isimli bir dosya oluşturalım ve ilgili hesabın şifresini bu dosyaya yazalım.

Node1'i ayağa kaldırmak için komutu oluşturalım.

geth --networkid 1881 --datadir "node1/" --bootnodes 'enode://b19a42e8bf96953a0e365fbfbea7fba8aab55a057c086d12bd8584115e6e8b66e9a98d739e021eba2fb4b6f3eb451ffeef1287950cd596a80c88fbddc26ea6dc@127.0.0.1:30304  --port  30305 --ipcdisable --syncmode full --rpc --rpcaddr 0.0.0.0 --rpccorsdomain "*" --rpcport 8546 --unlock 29e97a93c40d91a6cc86a03668bebecc3b989494 --password node1/password.txt --mine  --keystore 'node1/keystore' console

komutu çalıştırınca node1 ayağa kalkar fakat herhangi bir mine işlemi yapmadığını ve blok oluşturmadığını göreceksinizdir.  Sebebi ise bütün sealer node'ların ayakta olmamasıdır.

ikinci sealer node yani node2'yi ayağa kaldıralım.

geth --networkid 1881 --datadir "node2/" --bootnodes 'enode://b19a42e8bf96953a0e365fbfbea7fba8aab55a057c086d12bd8584115e6e8b66e9a98d739e021eba2fb4b6f3eb451ffeef1287950cd596a80c88fbddc26ea6dc@127.0.0.1:30304'  --port  30306 --ipcdisable --syncmode full --rpc --rpcaddr 0.0.0.0 --rpccorsdomain "*" --rpcport 8547 --unlock df6cc60abfdfdef40be53c75962b666a9febd3ef --password node2/password.txt --mine  --keystore 'node2/keystore' console

İki adet sealer node ayağa kaldırdık. İsterseniz bir tanede transaction node ayağa kaldıralım. Yani mine işlemi yapmasın.

geth --networkid 1881 --datadir "node3/" --bootnodes 'enode://b19a42e8bf96953a0e365fbfbea7fba8aab55a057c086d12bd8584115e6e8b66e9a98d739e021eba2fb4b6f3eb451ffeef1287950cd596a80c88fbddc26ea6dc@127.0.0.1:30304'  --port  30307 --ipcdisable --syncmode full --rpc --rpcaddr 0.0.0.0 --rpccorsdomain "*" --rpcport 8548 --unlock console


2 adet miner bir adet transaction node ile  networkümüzü kurmuş bulunuyoruz.

Networkü kurarken ufak tefek problemlerle karşılaşmış olabilirsiniz ama yinede yılmadan çalıştırmaya çalışınız bir problem yaşarsanız lütfen sonmezosman@gmail adresine istediğiniz zaman mail atabilirsiniz.




13 Ocak 2019 Pazar

.Net Core, MACOS ve JetBrains Rider

Bildiğimiz gibi .NET Core ile birlikte .NET ile kod geliştirmek işletim sistemi  bağımsız hale geldi. Durum böyle olunca yazdığımız kodları Linux ve MACOS ortamında çalıştırmak .NET geliştiricileri için büyük bir avantaj haline geldi.
.NET Core maceramız nasıl başladı ilk olarak oradan başlayayım. .Net 4.5.2 ile geliştirdiğimiz bir projemizi microservis olarak yazmaya karar verdik. .NET framework ile devam etmek yerine .NET Core ile yazıp yazamayacağımızı araştırdık. Projenin 3. parti dll bağımlılığı vardı ve firma .NET CORE versiyonunu çıkarmamıştı. 2019 'da çıkaracağız diye cevap döndüler. Mecburen .NET 4.6.1 ile geliştirmeye başladık. Microservisleri ise mecburen Service Fabric ile çalıştırmayı planladık. Üzülerek söylüyorum ki Microsoft firmasının geliştirdiği .NET framework'un sadece windows ortamında çalışmasından dolayı microservis projemizi mecburen yine microsoftun sunduğu platformda koşturmak durumundaydık. Openshift windows desteğini henüz sağlamamıştı (2019 başında cıkacak demişlerdi).  Projenin ilk sürümünü .NET 4.6.1 ile çıkardıktan sonra ekip olarak bu kadar platform bağımlı olmak çok da içimize sinmedi.  Madem böyle bir proje yapıyoruz, microservis ve container yapısı bizim içinde yeni ve güzel bir tecrübe oluyor platform bağımlılığından bir şekilde kurtulup yazdığımız kodları istediğimiz ortamda  çalıştırıp denemeliyiz diye düşündük. İşe ilk olarak 3. parti kullandığımız dll'leri decompile yapıp .NET standart projesine dönüştürmeye çalışmakla başladık. İlk başta kuşkuluyduk fakat decompile işlemlerini başarılı bir şekilde yaptıktan sonra ve .NET Standart projelerini oluşturunca, bütün projeyi .NET CORE ile yeniden yazmaya cesaretimiz arttı. Decompile işlemlerinde .NET framework ortamında olup .NET Core ortamında olmayan kütüphaneler olabiliyor bunların denklerini (open source kütüphaneler) bulmalısınız veya yöntem değişikliğine gitmek zorunda kalabilirsiniz. Microservis projemizi .NET Core ile geliştirmeye başladık. Ekipteki herkes .NET Core'da  yeni olmasına rağmen büyük bir iştahla bir çok konuyu araştırıp en iyisini yapmaya çalıştık.  Projenin ilk çıktılarını Openshift  platformunda Redhat Linux ile çalıştırdık. Windows'ta kodladık Linux ortamında çalıştırdık. İşletim sistemi bağımsızlığı gerçekten güzel birşeymiş. .NET CORE geliştiricilerine teşekkürler. Tabii işletim sistemi bağımsızlığı gelince geliştirme işini de  diğer  işletim sistemlerinde de denemeye karar verdik. İlk olarak MACOS ile başladık.  MACOS ortamına da oldukça yabancıydık.  Windowsa alışınca MACOS ve Linux biraz korkutucu geliyor.  Bazılarınızın ne gerek var dediğini duyar gibiyim ama  bende şimdiye kadar bu kadar windows  bağımlısı kaldığım için  bir developer olarak kendimden utanıyorum diyorum. Birçok platforma hakim olmamız gerektiğini şuan rahatlıkla söyleyebiliyorum. 
MACOS ortamında .NET Core ile geliştirme yapmak için visual studio for mac, visual studio code veya JET Brains Rider kullanabilirsiniz.  Bir kaç arkadaşım Jet Brains Rider kullanmam gerektiğini visual studio for mac'in windows'ta bulunan visual studio ile aynı olmadığını söyledi. Daha az özelliği olduğundan bahsettiler. Visual Studio Code'u zaten çoğunuz biliyordur, kullanım amacı biraz daha farklı bir react projesini visual studio code ile geliştirmek güzel olabiliyor, özellikle javascript geliştiriceleri çok fazla rahatlık intellisense aramıyor ama .NET geliştiricileri alıştıkları Visual Studio özelliklerini arıyor. Visual Studio Code'un Visual Studio rahatlığına ulaşması biraz zaman alacaktır. Seçenek olarak geriye JetBrains Rider kaldı. Yalnız Jet Brains Rider'ın ücretsiz sürümünü direkt olarak edinemiyorsunuz. Resharper'ı birçoğunuz duymuştur. Resharper ürününü üreten firma aynı zamanda Rider'ı üretiyor. Zaten elimizde Resharper lisansı vardı.  Üzerine  bir miktar daha ödeme yaparak yaklaşık 150$ gibi bir miktar. Rider'ı denemeye karar verdik. Daha sonra baktığımda Rider'ın öğrenciler, öğretmenler, startuplar ve  geliştirici toplulukları için ücretsiz veya indirimli olduğunu gördüm. 

Rider'ı https://www.jetbrains.com/rider/download/download-thanks.html adresinden indirip kullanmaya başlayabilirsiniz. sadece MACOS ortamında değil windows ortamında da kullanabilirsiniz. 

Rider'ı kullanmaya başlayıp keşfettikçe hoşunuza gideceğini düşünüyorum. Her tarafında farklı bir özellik var. Visual Studio'da olan Rider'da olmayan birşeye rastlamadım. Rider'da fazlası var diyebilirim. Visual Studio'da olmayan ve Rider'da karşılaştığım en önemli ve hoşuma gider özellik ise kullandığınız her kütüphaneyi decompile yapıp debug yapmanızı sağlaması. .NET Core ile birlikte kullandığınız kütüphanelerin çoğunun open source ve  neredeyse çok az dökümantasyona sahip olduğunu düşünürsek kendi kodunuzu debug esnasında kullandığınız kütüphaneleri de debug yapıp neler yaptıklarını görmek ve anlamak hoşunuza gidecektir. 

























Visual Studio'da görmediğim Rider ile gelen özelliklerden ilki 3. parti kütüphaneleri on the fly  decompile ve debug özelliği idi.

Diğer bir özellik ise kendi içinde gelen bir  REST Client'ı olması. Bildiğiniz bir nevi Postman'i adamlar Rider'ın içine eklemişler. REST  Api'lerinizi ayağa kaldırdıktan sonra buradan  request atabilirsiniz.



Yine alt menülerde
TODO : TODO' larınızı tek bir ekrandan görebilirsiniz.



Package yönetimi ekranı. Bizde nuget.org ve nexus üzerinden paketlerimizi yönetiyoruz.




Version Control : Biz Git  kullanıyoruz. Rider'ın gerçektende çok güzel bir Git yönetim ekranı var. Branch üzerinde yaptığımız bütün değişiklikleri buradan yönetebiliyoruz.  Aynı zamanda yaptığımız değişikliğin local ve remote branch arasındaki farkı anında gösteriyor.  Git'i komut ekranından yönetmek istemeyen ve görsel bir ekran isteyenler için bire bir.




Unittest, Terminal ve TeamCity gibi menülerde alt menüde listelenmiş durumda. Rider'ın alt menüsü bir çok ihtiyacınızı karşılayacak düzeyde ve yeterlilikte.

Tabii henüz bende 1 haftadır MACOS ortamında Rider üzerinde geliştirme yapıyorum. Muhtemelen henüz yüzde 10 özelliğini keşfetmişimdir ama bu haliyle bile Visual Studio eksikliğini aramadım fazlası var eksiği yok diyebiliyorum.

Bizim Core Framework solution da 20 adet proje olmasına rağmen açılış ve build hızı da gayet iyi.


Projeler sol tarafta listeleniyor. Biliyorsunuz eğer Visual Studio'yu özelleştirmediyseniz solution explorer  default sağdadır. Burada ise default olarak solda açılıyor. Solution yapısıda biraz Visual Studio Code gibi. Direkt klasör yapısını görüyorsunuz. Hem solution hem klasör yapısını aynı anda görmekde hoşunuza gidebilir. Özellikle bu tarz editör kullanmış olanlar alışmak için zorluk çekmeyecektir.













MACOS ortamında veya Linux ortamında kodunuzu build etmek ve çalıştırmanın  bir diğer faydasıda windows ortamında çalışan bazı kodların burada çalışmadığını veya farklı şekilde yazılması gerektiğini anlamanız oluyor. Mesela Server IP adresini aldığımız kodun MACOS ortamında çalışmadığını görmem iyi oldu. Her platformda çalışacak şekilde değiştirdim.

Yazıyı çok da uzun tutmak istemiyorum. Rider üzerinde çalıştıkça tecrübelerimi paylaşmak ve siz değerli yazılımcı arkadaşlarıma faydalı olmak istiyorum. Umarım yararlı olmuşumdur. Umarım benim gibi yıllarca windows ortamında çalışan ve diğer işletim sistemi ve platformları tecrübe etmek isteyen arkadaşlarıma  cesaret verebilmişimdir. Rider beni çok şaşırttı. Gerçekten geliştiren ekibi tebrik ediyorum. Teşekkürler.