From f89af8add4e7d19e6607708879150890e4a7f072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sad=C4=B1k=20S=C3=BCnb=C3=BCl?= <109942759+SadikSunbul@users.noreply.github.com> Date: Sat, 22 Jun 2024 10:39:44 +0300 Subject: [PATCH] =?UTF-8?q?merkle=20tree=20yaz=C4=B1ld=C4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blockchain/block.go | 26 +++++++----------- blockchain/blockchain.go | 38 +++++++++++++++++++------- blockchain/merkle.go | 55 ++++++++++++++++++++++++++++++++++++++ blockchain/transaction.go | 25 +++++++---------- cli/cli.go | 8 +++--- tmp/blocks/000000.vlog | Bin 2180 -> 3151 bytes tmp/blocks/000008.sst | Bin 464 -> 534 bytes tmp/blocks/MANIFEST | Bin 434 -> 434 bytes tmp/wallets.data | Bin 2084 -> 1222 bytes 9 files changed, 107 insertions(+), 45 deletions(-) create mode 100644 blockchain/merkle.go diff --git a/blockchain/block.go b/blockchain/block.go index 88c77a7..b552cb4 100644 --- a/blockchain/block.go +++ b/blockchain/block.go @@ -2,7 +2,6 @@ package blockchain import ( "bytes" - "crypto/sha256" "encoding/gob" "log" ) @@ -14,27 +13,19 @@ type Block struct { Nonce int } +// HashTransactions fonksiyonu, bloğun islemlerini hash eder func (b *Block) HashTransactions() []byte { - var txHashes [][]byte // İşlemlerin kimliklerini (hash'lerini) tutmak için bir slice tanımlıyoruz - var txHash []byte // Son hesaplanan hash'i tutacak byte slice + var txHashes [][]byte - // Bloktaki her bir işlem için döngü - for _, tx := range b.Transactions { - txHashes = append(txHashes, tx.ID) // Her işlemin ID'sini (hash'ini) txHashes slice'ına ekliyoruz + for _, tx := range b.Transactions { //islemi byte dizisine dönüştürür + txHashes = append(txHashes, tx.Serialize()) //islemi byte dizisine dönüştürür } + tree := NewMerkleTree(txHashes) //merkle tree olusturulur - // txHashes içindeki tüm işlem kimliklerini birleştirip tek bir byte dizisi oluşturuyoruz - concatenated := bytes.Join(txHashes, []byte{}) - - // concatenated byte dizisinin SHA-256 hash'ini hesaplıyoruz - hash := sha256.Sum256(concatenated) - - // [32]byte türündeki hash'i []byte türüne dönüştürüyoruz - txHash = hash[:] - - return txHash[:] // Hesaplanan hash'i döndürüyoruz + return tree.RootNode.Data //merkle treein rootunun byte dizisine dönüştürülür } +// CreateBlock fonksiyonu, yeni bir bloğu olusturur func CreateBlock(tsx []*Transaction, prevHash []byte) *Block { block := &Block{[]byte{}, tsx, prevHash, 0} //[]byte(data) kısmı strıng ıfadeyi byte dizisine donduruyor @@ -45,12 +36,14 @@ func CreateBlock(tsx []*Transaction, prevHash []byte) *Block { return block } +// Genesis fonksiyonu, ilk bloğu olusturur func Genesis(coinbase *Transaction) *Block { return CreateBlock([]*Transaction{coinbase}, []byte{}) } //Badger DB sadece byte kabul ettıgı ıcın serılestırme ve deserilize ıslemlerı kolyalastıralım +// Serialize fonksiyonu, bloğu byte dizisine dönüştürür func (b *Block) Serialize() []byte { var res bytes.Buffer // bir bytes.Buffer nesnesi oluşturuluyor @@ -86,6 +79,7 @@ func Deserilize(data []byte) *Block { return &block } +// Handle fonksiyonu, oluşan hata durumunda programı durdurur. func Handle(err error) { if err != nil { log.Panic(err) diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index d75b0b2..478e2a7 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "github.com/dgraph-io/badger" + "log" "os" "runtime" ) @@ -109,26 +110,38 @@ func InitBlockChain(address string) *BlockChain { } // AddBlock block zincirine blok elememızı saglar -func (chain *BlockChain) AddBlock(transactions []*Transaction) { - var lastHash []byte //son blogu tutucak - err := chain.Database.View(func(txn *badger.Txn) error { //verıtabanında okuma ıslemı yapıca k - item, err := txn.Get([]byte("lh")) //lh degerını oku +func (chain *BlockChain) AddBlock(transactions []*Transaction) *Block { + var lastHash []byte //lastHash degerini olusturduk + + for _, tx := range transactions { //gelen transactionları döndürerek + if chain.VerifyTransaction(tx) != true { //Gelen transactionları kontrol edip + log.Panic("Invalid Transaction") //Hatalı bir transaction varsa hata mesajını verir + } + } + + err := chain.Database.View(func(txn *badger.Txn) error { //veritabanından son hash degerini alıyoruz + item, err := txn.Get([]byte("lh")) //son hash degerini alıyoruz Handle(err) - lastHash, err = item.ValueCopy(nil) //degeri kopyala + lastHash, err = item.ValueCopy(nil) //son hash degerini alıyoruz + return err }) Handle(err) - newBlock := CreateBlock(transactions, lastHash) //blogu olusturt - err = chain.Database.Update(func(txn *badger.Txn) error { //verıtabanında bır guncelleme ekleme yapılıcak - err := txn.Set(newBlock.Hash, newBlock.Serialize()) //yenı blogu verıtabanına ekle + newBlock := CreateBlock(transactions, lastHash) //yeni blok olusturuyoruz + + err = chain.Database.Update(func(txn *badger.Txn) error { //veritabanına yeni blok ekliyoruz + err := txn.Set(newBlock.Hash, newBlock.Serialize()) //yeni blok veritabanına kaydediliyor Handle(err) - err = txn.Set([]byte("lh"), newBlock.Hash) //lh degerını guncelle + err = txn.Set([]byte("lh"), newBlock.Hash) //son hash degeri veritabanına kaydediliyor + + chain.LastHash = newBlock.Hash //son hash degeri veritabanına kaydedildi - chain.LastHash = newBlock.Hash //mevcut Blockchain nesenesındekı lastHası guncelle cunku artık son uretılen blog newBlock return err }) Handle(err) + + return newBlock } // Iterator :BlockChaın de okuma işlemi yapmak için başlangıç değerlerini atayan kod @@ -287,6 +300,11 @@ func (bc *BlockChain) SignTransaction(tx *Transaction, privKey ecdsa.PrivateKey) // VerifyTransaction fonksiyonu, bir Transaction yapısının geçerliliğini doğrular. // Geçerlilik kontrolü için verilen önceki işlemler haritası (prevTXs) kullanılır. func (bc *BlockChain) VerifyTransaction(tx *Transaction) bool { + + if tx.IsCoinbase() { + return true + } + prevTXs := make(map[string]Transaction) // Önceki işlemlerin haritasını (map) oluşturur // İşlemdeki her girdi için önceki işlemi bulup prevTXs haritasına ekler diff --git a/blockchain/merkle.go b/blockchain/merkle.go new file mode 100644 index 0000000..9c65d8b --- /dev/null +++ b/blockchain/merkle.go @@ -0,0 +1,55 @@ +package blockchain + +import "crypto/sha256" + +type MerkleTree struct { + RootNode *MerkleNode +} + +type MerkleNode struct { + Left *MerkleNode + Right *MerkleNode + Data []byte +} + +func NewMerkleNode(left, right *MerkleNode, data []byte) *MerkleNode { + node := MerkleNode{} + + if left == nil && right == nil { + hash := sha256.Sum256(data) + node.Data = hash[:] + } else { + prevHash := append(left.Data, right.Data...) + hash := sha256.Sum256(prevHash) + node.Data = hash[:] + } + + node.Left = left + node.Right = right + + return &node +} + +func NewMerkleTree(data [][]byte) *MerkleTree { + var nodes []MerkleNode + if len(data)%2 != 0 { + data = append(data, data[len(data)-1]) + } + + for _, data := range data { + node := NewMerkleNode(nil, nil, data) + nodes = append(nodes, *node) + } + + for i := 0; i < len(data)/2; i++ { + var level []MerkleNode + for j := 0; j < len(nodes); j += 2 { + node := NewMerkleNode(&nodes[j], &nodes[j+1], nil) + level = append(level, *node) + } + nodes = level + } + + tree := MerkleTree{&nodes[0]} + return &tree +} diff --git a/blockchain/transaction.go b/blockchain/transaction.go index 5cb8bdf..1f7f69a 100644 --- a/blockchain/transaction.go +++ b/blockchain/transaction.go @@ -24,30 +24,23 @@ type Transaction struct { // CoinbaseTx fonksiyonu, bir coinbase transaction oluşturur. func CoinbaseTx(to, data string) *Transaction { if data == "" { //data boş ise gir - data = fmt.Sprintf("Coins to %s", to) //paralar to da der + randData := make([]byte, 24) //data 24 byte'lık bir diziye dönüştür + _, err := rand.Read(randData) //rastgele sayı uretıcısı ile diziye dönüştür (diziyi doldur) + if err != nil { + log.Panic(err) + } + data = fmt.Sprintf("%x", randData) // diziyi stringe doğru dönüştür + } txin := TxInput{[]byte{}, -1, nil, []byte(data)} //hıcbır cıktıya referabs vermez ,cıkıs endexi -1 aynı referans yok , sadce data mesajı vardır - txout := NewTXOutput(100, to) //100 tokeni to ya gonderırı + txout := NewTXOutput(20, to) //100 tokeni to ya gonderırı tx := Transaction{nil, []TxInput{txin}, []TxOutput{*txout}} //transectıonı olustururuz - tx.SetID() //Transectıon Id sını olustururuz + tx.ID = tx.Hash() //Transectıon hashini olustururuz //Transectıon Id sını olustururuz return &tx } -// SetID fonksiyonu, Transectıon Id sını olusturur. -func (tx *Transaction) SetID() { //Id olusturur transectıonun - var encoded bytes.Buffer - var hash [32]byte - - encode := gob.NewEncoder(&encoded) - err := encode.Encode(tx) //transectıonu encode edıyoruz - Handle(err) - - hash = sha256.Sum256(encoded.Bytes()) //transectıonu byte seklınde sha256 ıle sıfrelıyoruz ve ıd yı urettık - tx.ID = hash[:] -} - // NewTransaction, belirtilen bir adresten başka bir adrese belirtilen miktar token transferi yapacak yeni bir işlem oluşturur. func NewTransaction(from, to string, amount int, UTXO *UTXOSet) *Transaction { var inputs []TxInput // Bu işlemdeki girdiler (inputs) diff --git a/cli/cli.go b/cli/cli.go index 9b827e5..5c33567 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -125,9 +125,11 @@ func (cli *CommandLine) send(from, to string, amount int) { UTXOSet := blockchain.UTXOSet{chain} // gonderenin UTXO setini oluşturur defer chain.Database.Close() // blok zincirini kapat - tx := blockchain.NewTransaction(from, to, amount, &UTXOSet) // yeni bir işlem oluşturur - chain.AddBlock([]*blockchain.Transaction{tx}) // blok zincirine ekler - fmt.Println("\u001B[32mSuccess!\u001B[0m") // basarılı mesajı verir + tx := blockchain.NewTransaction(from, to, amount, &UTXOSet) // yeni bir işlem oluşturur + cbTx := blockchain.CoinbaseTx(from, "") //madencının parasını verıcezdrom olan madencı burada + block := chain.AddBlock([]*blockchain.Transaction{cbTx, tx}) // blok zincirine ekler + UTXOSet.Update(block) // UTXO setini yeniden oluşturur + fmt.Println("\u001B[32mSuccess!\u001B[0m") // basarılı mesajı verir } // listAddresses fonksiyonu, cüzdan adreslerini listeler. diff --git a/tmp/blocks/000000.vlog b/tmp/blocks/000000.vlog index 86ca7e77bf153f1d99ad482eb08dda763e145907..a309afc3554afc8e74e190e4df49e2f01f5fb15f 100644 GIT binary patch literal 3151 zcmZQzVBlh4U{C;JFmPbV$@mWe{}>nqw(ktjxO5>uu~j=g=~dw#E(!MsKlyJ;?R;Lb zYPa6=_oik*O&Sagj31!d861EN{JLPKyZ-NHW@Kb_%E?d8X8hm7z{tYL;*nUK!N|qH z$P-eOm{**bT#}ieSIqdokAaaRpeVHrCe7-XpO>7<$O5wbe=idwqhxffRuagdy0?P+9`Ctc`(@-M_R1!s!B9q5QuU zXoX00EV2z1VC7)d|63RsZ2va{O=k~*3Acc}12vf$Xd2M1jGV!l>3NAIrA4V=`vOXn zyi+TIOa=y(|D8Y^MA2-3ID+wi7X#z}4h9Cj|Ls64I6^95;vEc(OpL5yi8-a9pkU+# z8km!r3^Vh8|NkCF1wxU*$jGQ5v@fm0`;$4tyC7}Orv0mTDYgrFh%eJ`(v7`4d2yaT z10&EHCONmvqT&(-aPXyq<3%B@C_h&rJvA@2II|e2h*5)4#46Rv5>Kg+C(_d)~1BPkIX>CBi3Ij1C5Q9MjgJM!*N_uLMVo60FEMXWLi@aI~l-32} z84z_0z;snwQjxDq$gNN_{-}Usn-dmTz-R@=H86tU5essP3OHhM1v@YufMQk;9J5Hl z4vbnn!7lf|313jGUT|0uXfwe;_+$JvYt?q3N?e)q7cgB;V1C1Bq5J+u?&IFMYb(B6 zPyYUS|2eb0$5q_Uz6m^Xf#nNOKQMDLs{&~-Z~&6{bwR`L*J$RXY3BULco>p9@y7-* zp(#9*k&omu`~J@Tm*e)NgjIz}d-wIOj+8K8(QZHgikNsZICmPPC7YTi8kv|Hn;TeI znph;JnHwaU8JVY~CZ(AqTPB(%rlxWjP9|@J#kog^o7K0ws3*HKIWh6Bpdog za=mB!iZwg@I=b9PdCr2{XJ201{fqs#!X?)I7a}*$>S8hwaoTjHG?&rge9UWe?x%|L zccoo4zkK=gioXwLPgYIRJ#~BeyEvi4D!uXhj!JC^be*qix9F~RY(-w3%(7JrI2YO_ za&0;y$ge95%Boz9BCi`-8_f>!Ur3j9$^2u>l6}wV&U^+&Ib7uxqXNNV^DpBMEr!=( zGE0FuieP5`Wx9(+CKsp@TZu*}exW(?r^^3+VDXP!qD??8(LhxdEh-YZ{}b?)XciW) z!k}IQQV`%sQepjb59h&yK#ic#*$6cOR^Agzhyxxv=D^S)Cylk0vSa}LN-*vGG@HBG z9TX^_(18PJ023KH-zF-W(1MR@4L!6R-$U}?-oY|verT^L$AGwwCvkpt-Xzz lXOuv_MrJ}CIIo!l8z$r=RMBZMOMreRm{7l2s@yER2>^_AS04ZX literal 2180 zcmZQzV9;P-VEo7c1r9)3V{JZfR#%kMB{Q}D&((W>ddv;-Fk9_@M?iQ^kL2$E5b)3S ze>XEDBdb$ResVVB{~iWL7Dg72#NrG_E(S)PkfOxA;>6^V%>2A!#{Yc`j2r<)sbw%} zR=@nb_y5$;?30fNo{v49-l?ODriZN(I{&P@3eOS_xz_FsS_R1lk~qW&^|#jQ_hB82@)L zFzEen2U@`qQUMe1U|?ioWDQHqDFp=uBPYG{ukwpyG?=4eR`N4GRstnKM#D?j+H6JiAF#TnGq`|;t`XL(VS&)Z; z?t%aZhMWvof*|BpkL?>XfVzZ%m=UU-p@Bg$DKRBIwMem~A`fPep|QxTbwCxmKs*zs z(t)A0q#|FJkY}N0{80fX7fx7c1JeaCu>fNjo-*2i2CINm2CjGmCL~bO&;ut8q<90S z4LtEC|Gx=uSjOru)&yEjFckh6f6ZF89jFqRJ()HlLID_fhtjvska#xZQs>fxpZv@w z{Yz~7f35#q>8|H}c?H{{0q|=yd(t#}{$uoqW>>Tw&?9Xs?)5YdO6RP$xiONZw#YDl=kd$F@?JwXY#)N zUJ`1uK51c!&J!ozE-nVo9pS9ilO;_jw$*1`bKV~ICiZXB8JR1W5}Gw?r{uYoPh@-h zS79S4*>f?9JWg8Xv{J1$vpG{&hGwyuUNHP52OYN{y8x~ z0h1n(;lRMepvJ%t5>lSP{D#p&_x+9B$GvmcR(!Xf{QdL(b7p&wtGJzg6A01${})_4 zb20-1^If1m5wLbg#iYcP^wc87jMT&wsN%06V zkjn)&d2LPxhUGwaGceBuD$xZixm8+Hk+1t$Bv-p|v(L^P4=3R@E+_e27p2Qu9OiN0 zG=3|4H&{dkYRWgb7Z|=UFmM~fP5BEp<(Z6pB$wIuckaI&w{{%vQVK5fGl!Be@%*`~N?L zc73QhB4F)~ib;tn>8VAE8L5dWP{rS%Du9$00|Q4CkcKF3z@qpkiek2NKrR>9{WP*vN0@_$>_lU_WF0W$UGH&_xAkimrXS# z%jch6edpie!_z@F{XDfy4rmhx$fnGINyijgXWLZ$d+YZgj;raV@!ik=Pi~x**WS`2 Qcd+*%&?a`UO>6>;0J21zp#T5? literal 434 zcmZ=tNiSkxU|<1a7*N}nGvorZJU^4sgF9PKpWh%Qr6+c_GWNps z52EwFH~t4|(aSgx(9WgC!6ZS1dM*|YMgc~kF0}}u3papvFe@q4ZLX5iyR_qR+NH=hWPkm|$_mSGiGe8Bn#!wLhk+Ks#7KcFfi|+t^a^SbOW_$@?}RDe2Mr zExaTA?E~fiI(LE=mUQd~+QBTq2qc*xHib=id>3dFtCGTkwvb6r+@_~xOnxqK^=8}8 z+h_T{UvpiMbELvgNBQmK6Cj&@a@|`Cw22L5)9*E}_KRhgyNSf*Em-x$|G!%M)&9+y zDw_=}=CC%EyCeebU| QeSFn`HnD?kViRBl0NdJ`GXMYp diff --git a/tmp/wallets.data b/tmp/wallets.data index a7f2a08149d4bfd4c38d6a12a3e77e7350bd64cf..b9e22592ae3deae86c2f1fbe85809d0e1ef01a12 100644 GIT binary patch delta 444 zcmZ1?aEx=pa}_2fLo@H(u#9lSGV|=Ha9`)td_xmspG@D3U_bAoz@o6y4DZR@jI)@S z-3hRaF%9 zGM}zkuN`=ORu}`L16G^-k*p$UkCLHZs7rQfL0V{Xg|ll|Zb(H`pm}0oXlA})L8)(X zU|5ke&}(v&!?yJP>dP$(0Fa5MG zSo7fdi_ohJmUDWCr^aNKPYNkl-G2LvqK59b?pTn&`tQWJ9c%J^87jUouHf2yx1Beq dH`_n{d0*gsW2}{tBp=XUSZ&fpvWlQR3;?Kd!BYSL delta 876 zcmX@cxkO;Xa}^dPL$}R?{~SaHs-&ceaU-;qtF}k zo@a;o%(u+RJjTH2fYl~{B&!J8qhx4g?42G^nN;Ci5#(Z7kWms^5m4%zUX_)eQ4yG0 z66#wB^qSn{aOT7Hb}j!~ICLlMdVYJ}Dj)gpCpXLRF7UelW|G2Nd5Q9Wdwqd!mU!oW zT6+8YE^mz)Wg?PaIi=@c|{dk_!T(2CKfoSguD9qczc*sxP*K86q)(D znP(Wm{dKcwl_&4_x?>CSiZ6+Yo&03AMq^v-beZ(Zreh89f|($Hr5uW=*59?|%A(zy z-?(gwbagzjPsuR4`IODF1*_EiQf7htRk$SY1>Zie#&dzfYm6P99oVfZaG>DN(SIxr WqH{`?y>bTn3#(1KNLCTFhXDXOc6tv0