From e807b774b310daabd14e6cdf14f874541c439ccb 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: Fri, 21 Jun 2024 08:06:17 +0300 Subject: [PATCH] =?UTF-8?q?C=C3=BCzdan=20yap=C4=B1s=C4=B1=20eklendi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit *Para transferlerı ıcın cuzdan yapısı duzenlendi * Hatasız çalışıyor durumda * Terminal düzenlendi --- blockchain/blockchain.go | 67 +++++++++++--- blockchain/transaction.go | 185 ++++++++++++++++++++++++++++++++------ blockchain/tx.go | 54 +++++------ cli/cli.go | 86 +++++++++++------- main.go | 2 +- tmp/blocks/000000.vlog | Bin 4740 -> 1522 bytes tmp/blocks/000004.sst | Bin 0 -> 429 bytes tmp/blocks/000014.sst | Bin 744 -> 0 bytes tmp/blocks/MANIFEST | Bin 752 -> 222 bytes tmp/wallets.data | Bin 2085 -> 1222 bytes wallet/wallet.go | 6 +- 11 files changed, 303 insertions(+), 97 deletions(-) create mode 100644 tmp/blocks/000004.sst delete mode 100644 tmp/blocks/000014.sst diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index ad8cf98..91fe359 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -1,7 +1,10 @@ package blockchain import ( + "bytes" + "crypto/ecdsa" "encoding/hex" + "errors" "fmt" "github.com/dgraph-io/badger" "os" @@ -151,7 +154,7 @@ func (iter *BlockChainIterator) Next() *Block { } // FindUnspentTransactions : Bu fonksiyon, bir blockchain üzerinde belirli bir adrese gönderilmiş ancak henüz harcanmamış (unspent) işlemleri bulmak için kullanılır. -func (chain *BlockChain) FindUnspentTransactions(address string) []Transaction { +func (chain *BlockChain) FindUnspentTransactions(pubKeyHash []byte) []Transaction { var unspentTxs []Transaction // Harcanmamış işlemleri tutacak slice spentTXOs := make(map[string][]int) // Harcanmış işlemlerin çıktılarını izlemek için kullanılacak map @@ -175,7 +178,7 @@ func (chain *BlockChain) FindUnspentTransactions(address string) []Transaction { } // Eğer çıktı, belirtilen adrese gönderilmişse - if out.CanBeUnlocked(address) { //aranan adres tarafından acılıp acılmayacagı kontrol edılır + if out.IsLockedWithKey(pubKeyHash) { //aranan adres tarafından acılıp acılmayacagı kontrol edılır unspentTxs = append(unspentTxs, *tx) // Harcanmamış işlemler listesine ekle } } @@ -185,7 +188,7 @@ func (chain *BlockChain) FindUnspentTransactions(address string) []Transaction { // İşlemin girdileri üzerinde döngü for _, in := range tx.Inputs { // Eğer bu girişin kilidi (unlock) belirtilen adrese açılabiliyorsa - if in.CanUnlock(address) { + if in.UsesKey(pubKeyHash) { inTxID := hex.EncodeToString(in.ID) // Girişin işlem ID'sini alarak hex formatına dönüştür spentTXOs[inTxID] = append(spentTXOs[inTxID], in.Out) // Harcanmış işlemler listesine ekle } @@ -203,13 +206,13 @@ func (chain *BlockChain) FindUnspentTransactions(address string) []Transaction { } // FindUTXO fonksiyonu, belirtilen bir adrese gönderilmiş ve henüz harcanmamış (UTXO) çıktıları bulmak için kullanılır. -func (chain *BlockChain) FindUTXO(address string) []TxOutput { - var UTXOs []TxOutput // Harcanmamış çıktıları (UTXO'ları) tutacak slice oluşturulur - unspentTransactions := chain.FindUnspentTransactions(address) // Belirtilen adrese gönderilmiş harcanmamış işlemleri bul +func (chain *BlockChain) FindUTXO(pubKeyHash []byte) []TxOutput { + var UTXOs []TxOutput // Harcanmamış çıktıları (UTXO'ları) tutacak slice oluşturulur + unspentTransactions := chain.FindUnspentTransactions(pubKeyHash) // Belirtilen adrese gönderilmiş harcanmamış işlemleri bul for _, tx := range unspentTransactions { // Her harcanmamış işlem için döngü for _, out := range tx.Outputs { // İşlemin çıktıları üzerinde döngü - if out.CanBeUnlocked(address) { // Çıktı, belirtilen adrese gönderilmişse + if out.IsLockedWithKey(pubKeyHash) { // Çıktı, belirtilen adrese gönderilmişse UTXOs = append(UTXOs, out) // UTXO'lar listesine çıktıyı ekle } } @@ -219,9 +222,9 @@ func (chain *BlockChain) FindUTXO(address string) []TxOutput { // FindSpendableOutputs, belirtilen bir adrese gönderilmiş ve henüz harcanmamış çıktıları (UTXO'ları) bulmak için kullanılır. // Ayrıca, bu çıktılar aracılığıyla belirli bir miktar token transfer edilebilecek çıktıları belirler. -func (chain *BlockChain) FindSpendableOutputs(address string, amount int) (int, map[string][]int) { - unspentOuts := make(map[string][]int) // Harcanmamış çıktıları (UTXO'ları) tutacak map - unspentTxs := chain.FindUnspentTransactions(address) // Belirtilen adrese gönderilmiş harcanmamış işlemleri bul +func (chain *BlockChain) FindSpendableOutputs(pubKeyHash []byte, amount int) (int, map[string][]int) { + unspentOuts := make(map[string][]int) // Harcanmamış çıktıları (UTXO'ları) tutacak map + unspentTxs := chain.FindUnspentTransactions(pubKeyHash) // Belirtilen adrese gönderilmiş harcanmamış işlemleri bul accumulated := 0 // Toplam biriktirilen miktar @@ -230,7 +233,7 @@ Work: txID := hex.EncodeToString(tx.ID) // İşlem ID'sini hex formatına dönüştür for outIdx, out := range tx.Outputs { // İşlemin çıktıları üzerinde döngü - if out.CanBeUnlocked(address) && accumulated < amount { // Çıktı, belirtilen adrese gönderilmiş ve biriktirilen miktar istenilen miktarı aşmamışsa + if out.IsLockedWithKey(pubKeyHash) && accumulated < amount { // Çıktı, belirtilen adrese gönderilmiş ve biriktirilen miktar istenilen miktarı aşmamışsa accumulated += out.Value // Çıktının değerini biriktirilen miktar'a ekle unspentOuts[txID] = append(unspentOuts[txID], outIdx) // Harcanmamış çıktıları map'e ekle @@ -243,3 +246,45 @@ Work: return accumulated, unspentOuts // Biriktirilen toplam miktarı ve harcanmamış çıktıları map olarak döndür } +func (bc *BlockChain) FindTransaction(ID []byte) (Transaction, error) { + iter := bc.Iterator() + + for { + block := iter.Next() + + for _, tx := range block.Transactions { + if bytes.Compare(tx.ID, ID) == 0 { + return *tx, nil + } + } + + if len(block.PrevHash) == 0 { + break + } + } + + return Transaction{}, errors.New("Transaction does not exist") +} +func (bc *BlockChain) SignTransaction(tx *Transaction, privKey ecdsa.PrivateKey) { + prevTXs := make(map[string]Transaction) + + for _, in := range tx.Inputs { + prevTX, err := bc.FindTransaction(in.ID) + Handle(err) + prevTXs[hex.EncodeToString(prevTX.ID)] = prevTX + } + + tx.Sign(privKey, prevTXs) +} + +func (bc *BlockChain) VerifyTransaction(tx *Transaction) bool { + prevTXs := make(map[string]Transaction) + + for _, in := range tx.Inputs { + prevTX, err := bc.FindTransaction(in.ID) + Handle(err) + prevTXs[hex.EncodeToString(prevTX.ID)] = prevTX + } + + return tx.Verify(prevTXs) +} diff --git a/blockchain/transaction.go b/blockchain/transaction.go index cfaad61..c860454 100644 --- a/blockchain/transaction.go +++ b/blockchain/transaction.go @@ -2,11 +2,17 @@ package blockchain import ( "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" "crypto/sha256" "encoding/gob" "encoding/hex" "fmt" + "github.com/SadikSunbul/GO-BlockChain-Simulation/wallet" "log" + "math/big" + "strings" ) type Transaction struct { @@ -20,11 +26,11 @@ func CoinbaseTx(to, data string) *Transaction { data = fmt.Sprintf("Coins to %s", to) //paralar to da der } - txin := TxInput{[]byte{}, -1, data} //hıcbır cıktıya referabs vermez ,cıkıs endexi -1 aynı referans yok , sadce data mesajı vardır - txout := TxOutput{100, to} //100 tokeni to ya gonderı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ı - tx := Transaction{nil, []TxInput{txin}, []TxOutput{txout}} //transectıonı olustururuz - tx.SetID() //Transectıon Id sını olustururuz + tx := Transaction{nil, []TxInput{txin}, []TxOutput{*txout}} //transectıonı olustururuz + tx.SetID() //Transectıon Id sını olustururuz return &tx } @@ -42,44 +48,40 @@ func (tx *Transaction) SetID() { //Id olusturur transectıonun // 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, chain *BlockChain) *Transaction { - var inputs []TxInput // İşlem girişleri (input'ları) için boş slice - var outputs []TxOutput // İşlem çıktıları (output'ları) için boş slice + var inputs []TxInput + var outputs []TxOutput - // Gönderen adresten belirtilen miktar kadar harcanabilir çıktıları bul - acc, validOutputs := chain.FindSpendableOutputs(from, amount) + wallets, err := wallet.CreateWallets() + Handle(err) + w := wallets.GetWallet(from) + pubKeyHash := wallet.PublicKeyHash(w.PublicKey) + acc, validOutputs := chain.FindSpendableOutputs(pubKeyHash, amount) - // Eğer hesaplanan toplam miktar istenilen miktardan az ise hata ver ve işlemi sonlandır if acc < amount { - log.Panic("Error: yeterli fon yok") + log.Panic("Error: not enough funds") } - // Geçerli (harcanabilir) çıktılar üzerinde döngü for txid, outs := range validOutputs { - txID, err := hex.DecodeString(txid) // İşlem ID'sini byte dizisine dönüştür - Handle(err) // Hata varsa işlemi sonlandır + txID, err := hex.DecodeString(txid) + Handle(err) - // Çıktı endeksleri üzerinde döngü for _, out := range outs { - input := TxInput{txID, out, from} // Yeni bir işlem girişi oluştur - inputs = append(inputs, input) // Oluşturulan girişi input'lar listesine ekle + input := TxInput{txID, out, nil, w.PublicKey} + inputs = append(inputs, input) } } - // Yeni bir çıktı oluştur ve belirtilen adrese belirtilen miktarı gönder - outputs = append(outputs, TxOutput{amount, to}) + outputs = append(outputs, *NewTXOutput(amount, to)) - // Eğer hesaplanan toplam miktar istenilen miktardan fazlaysa, geri kalan miktarı gönderen adrese geri gönder if acc > amount { - outputs = append(outputs, TxOutput{acc - amount, from}) + outputs = append(outputs, *NewTXOutput(acc-amount, from)) } - // Yeni bir işlem (transaction) oluştur tx := Transaction{nil, inputs, outputs} + tx.ID = tx.Hash() + chain.SignTransaction(&tx, w.PrivateKey) - // İşlem ID'sini hesapla ve işlem nesnesine ata - tx.SetID() - - return &tx // Oluşturulan işlem nesnesini işaretçi olarak döndür + return &tx } /* @@ -93,3 +95,136 @@ func (tx *Transaction) IsCoinbase() bool { // Bir coinbase işlemi sadece bir girişe sahiptir. // Bu girişin işlem kimliği (ID) uzunluğu 0'a eşit olmalıdır ve çıkış (Out) -1 olmalıdır. } + +func (tx Transaction) Serilize() []byte { + var encoded bytes.Buffer + enc := gob.NewEncoder(&encoded) + + err := enc.Encode(tx) + if err != nil { + log.Panic(err) + } + return encoded.Bytes() +} + +func (tx *Transaction) Hash() []byte { + var hash [32]byte + txCopy := *tx + txCopy.ID = []byte{} + hash = sha256.Sum256(txCopy.Serilize()) + return hash[:] +} + +func (tx *Transaction) Sign(privKey ecdsa.PrivateKey, prevTXs map[string]Transaction) { + if tx.IsCoinbase() { + return + } + + for _, in := range tx.Inputs { + if prevTXs[hex.EncodeToString(in.ID)].ID == nil { + log.Panic("ERROR: Previous transaction is not correct") + } + } + + txCopy := tx.TrimmedCopy() + + for inId, in := range txCopy.Inputs { + prevTX := prevTXs[hex.EncodeToString(in.ID)] + txCopy.Inputs[inId].Signature = nil + txCopy.Inputs[inId].PubKey = prevTX.Outputs[in.Out].PublicKey + txCopy.ID = txCopy.Hash() + txCopy.Inputs[inId].PubKey = nil + + r, s, err := ecdsa.Sign(rand.Reader, &privKey, txCopy.ID) + Handle(err) + signature := append(r.Bytes(), s.Bytes()...) + + tx.Inputs[inId].Signature = signature + + } +} + +func (tx *Transaction) Verify(prevTXs map[string]Transaction) bool { + if tx.IsCoinbase() { + return true + } + + for _, in := range tx.Inputs { + if prevTXs[hex.EncodeToString(in.ID)].ID == nil { + log.Panic("Previous transaction not correct") + } + } + + txCopy := tx.TrimmedCopy() + curve := elliptic.P256() + + for inId, in := range tx.Inputs { + prevTx := prevTXs[hex.EncodeToString(in.ID)] + txCopy.Inputs[inId].Signature = nil + txCopy.Inputs[inId].PubKey = prevTx.Outputs[in.Out].PublicKey + txCopy.ID = txCopy.Hash() + txCopy.Inputs[inId].PubKey = nil + + r := big.Int{} + s := big.Int{} + + sigLen := len(in.Signature) + r.SetBytes(in.Signature[:(sigLen / 2)]) + s.SetBytes(in.Signature[(sigLen / 2):]) + + x := big.Int{} + y := big.Int{} + keyLen := len(in.PubKey) + x.SetBytes(in.PubKey[:(keyLen / 2)]) + y.SetBytes(in.PubKey[(keyLen / 2):]) + + rawPubKey := ecdsa.PublicKey{curve, &x, &y} + if ecdsa.Verify(&rawPubKey, txCopy.ID, &r, &s) == false { + return false + } + } + + return true +} + +func (tx *Transaction) TrimmedCopy() Transaction { + var inputs []TxInput + var outputs []TxOutput + + for _, in := range tx.Inputs { + inputs = append(inputs, TxInput{in.ID, in.Out, nil, nil}) + } + + for _, out := range tx.Outputs { + outputs = append(outputs, TxOutput{out.Value, out.PublicKey}) + } + + txCopy := Transaction{tx.ID, inputs, outputs} + + return txCopy +} + +func (tx Transaction) String() string { + var lines []string + lines = append(lines, fmt.Sprintf("\033[35m ╔═══════════════════════════════════════════════════════════════════════════════════")) + lines = append(lines, fmt.Sprintf("\033[97m║\033[35m ║ --- Transaction %x:\033[0m", tx.ID)) + + for i, input := range tx.Inputs { + lines = append(lines, fmt.Sprintf("\033[97m║\033[38;5;94m ║ Input %d:\033[0m", i)) + + lines = append(lines, fmt.Sprintf("\033[97m║\033[33m ║ TXID: %x\033[0m", input.ID)) + lines = append(lines, fmt.Sprintf("\033[97m║\033[33m ║ Out: %d\033[0m", input.Out)) + lines = append(lines, fmt.Sprintf("\033[97m║\033[33m ║ Signature:%x\033[0m", input.Signature)) + lines = append(lines, fmt.Sprintf("\033[97m║\033[33m ║ PubKey: %x\033[0m", input.PubKey)) + } + + for i, output := range tx.Outputs { + lines = append(lines, fmt.Sprintf("\033[97m║\033[34m ║ Output %d:\033[0m", i)) + lines = append(lines, fmt.Sprintf("\033[97m║\033[36m ║ Value: %d\033[0m", output.Value)) + lines = append(lines, fmt.Sprintf("\033[97m║\033[36m ║ Script: %x\033[0m", output.PublicKey)) + } + + lines = append(lines, fmt.Sprintf("\033[97m║\033[35m ╚═══════════════════════════════════════════════════════════════════════════════════\033[0m")) + + return strings.Join(lines, "\n") +} diff --git a/blockchain/tx.go b/blockchain/tx.go index 936a477..418059f 100644 --- a/blockchain/tx.go +++ b/blockchain/tx.go @@ -1,36 +1,40 @@ package blockchain +import ( + "bytes" + "github.com/SadikSunbul/GO-BlockChain-Simulation/wallet" +) + type TxOutput struct { //transectıon cıktıları - Value int //token degeri - PubKey string //publıkkey sonra burası degısıcektır suan pubkey yerıne herhangıbır strıng deger kullanılıcak + Value int //token degeri + PublicKey []byte // public key hash } type TxInput struct { //transectıon girdileri - ID []byte //cıkısı referans eder - Out int //cıkıs endexı referans eder - Sig string //gırıs verısıdir + ID []byte //cıkısı referans eder + Out int //cıkıs endexı referans eder + Signature []byte // imza + PubKey []byte // public key +} + +func (in *TxInput) UsesKey(pubKeyHash []byte) bool { + lockingHash := wallet.PublicKeyHash(in.PubKey) + + return bytes.Compare(lockingHash, pubKeyHash) == 0 +} + +func (out *TxOutput) Lock(address []byte) { + pubKeyHash := wallet.Base58Decode(address) + pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-4] + out.PublicKey = pubKeyHash } -/* -CanUnlock metodunun görevi, bir işlem girişinin belirli bir veri ile kilidini açıp açamayacağını kontrol etmektir. -Genellikle işlem girişleri, işlemi imzalayan kişinin imzasını içerir. Bu metod, girişin imza alanının belirli bir -veri ile eşleşip eşleşmediğini kontrol eder. Eğer eşleşiyorsa, girişin doğru kişi tarafından yapıldığı doğrulanmış olur. -*/ -func (in *TxInput) CanUnlock(data string) bool { - return in.Sig == data - // Bu fonksiyon, bir işlem girişinin belirli bir veri ile kilidini açıp açamayacağını kontrol eder. - // Girişin imza (Sig) alanı, verilen data değeri ile eşleşiyorsa true döner. - // Bu, girişin sahibinin işlemi imzalayan doğru kişi olduğunu doğrular. +func (out *TxOutput) IsLockedWithKey(pubKeyHash []byte) bool { + return bytes.Compare(out.PublicKey, pubKeyHash) == 0 } -/* -CanBeUnlocked metodunun amacı, bir işlem çıkışının belirli bir veri ile kilidini açıp açamayacağını kontrol etmektir. -Çıkış genellikle genel anahtar (public key) ile kilitlenmiştir ve bu metod, çıkışın belirli bir genel anahtar ile -eşleşip eşleşmediğini kontrol eder. Eğer eşleşiyorsa, çıkışın doğru kişiye ait olduğu doğrulanmış olur. -*/ -func (out *TxOutput) CanBeUnlocked(data string) bool { - return out.PubKey == data - // Bu fonksiyon, bir işlem çıkışının belirli bir veri ile kilidini açıp açamayacağını kontrol eder. - // Çıkışın genel anahtarı (PubKey), verilen data değeri ile eşleşiyorsa true döner. - // Bu, çıkışın belirli bir kişiye ait olduğunu doğrular. +func NewTXOutput(value int, address string) *TxOutput { + txo := &TxOutput{value, nil} + txo.Lock([]byte(address)) + return txo } diff --git a/cli/cli.go b/cli/cli.go index 767e141..9cbec5c 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -8,6 +8,7 @@ import ( "log" "os" "runtime" + "strconv" ) // CommandLine struct, komut satırı işlemleri için kullanılan yapıyı temsil eder. @@ -17,13 +18,14 @@ type CommandLine struct { // PrintUsage fonksiyonu, komut satırında kullanıcıya kullanım talimatlarını gösterir. func (cli *CommandLine) printUsage() { - fmt.Printf("Usage:\n") - fmt.Printf(" %-40s : %s\n", "getbalance -address ADDRESS", "Belirtilen adrese ait bakiyeyi görüntüler") - fmt.Printf(" %-40s : %s\n", "createblockchain -address ADDRESS", "Yeni bir blok zinciri oluşturur ve belirtilen adrese oluşum ödülünü gönderir") - fmt.Printf(" %-40s : %s\n", "printchain", "Blok zincirindeki tüm blokları yazdırır") - fmt.Printf(" %-40s : %s\n", "send -from FROM -to TO -amount AMOUNT", "Belirtilen miktarı belirtilen adresten diğer bir adrese gönderir") - fmt.Printf(" %-40s : %s\n", "createwallet", "-Yeni bir cüzdan oluşturur") - fmt.Printf(" %-40s : %s\n", "listaddresses", "Cüzdan dosyamızdaki adresleri listeleyin\n") + fmt.Printf("\033[35mUsage:\n\033[0m") + fmt.Printf(" \033[35m%-40s : %s\n\033[0m", "getbalance -address ADDRESS", "Belirtilen adrese ait bakiyeyi görüntüler") + fmt.Printf(" \033[35m%-40s : %s\n\033[0m", "createblockchain -address ADDRESS", "Yeni bir blok zinciri oluşturur ve belirtilen adrese oluşum ödülünü gönderir") + fmt.Printf(" \033[35m%-40s : %s\n\033[0m", "printchain", "Blok zincirindeki tüm blokları yazdırır") + fmt.Printf(" \033[35m%-40s : %s\n\033[0m", "send -from FROM -to TO -amount AMOUNT", "Belirtilen miktarı belirtilen adresten diğer bir adrese gönderir") + fmt.Printf(" \033[35m%-40s : %s\n\033[0m", "createwallet", "Yeni bir cüzdan oluşturur") + fmt.Printf(" \033[35m%-40s : %s\n\033[0m", "listaddresses", "Cüzdan dosyamızdaki adresleri listeleyin\n") + } // validateArgs fonksiyonu, komut satırı argümanlarını doğrular. @@ -40,50 +42,69 @@ func (cli *CommandLine) validateArgs() { func (cli *CommandLine) printChain() { chain := blockchain.ContinueBlockChain("") // blockchain adında bir BlockChain nesnesi defer chain.Database.Close() // blok zincirini kapat - iter := chain.Iterator() // blok zinciri iteratorunu olustur + iter := chain.Iterator() // blok zinciri iteratorunu oluştur fmt.Println() + for { // blok zinciri sonuna kadar döngü block := iter.Next() // Sıradaki bloğu al - - fmt.Printf(" %-10s : %x\n", "Prev. hash", block.PrevHash) // Blok zincirinden o bloğun önceki hash değerini yazdır - fmt.Printf(" %-10s : %x\n", "Hash", block.Hash) // Blok zincirinden o bloğun hash değerini yazdır - + fmt.Println("\033[97m╔══════════════════════════════════════════ BLOCK ═════════════════════════════════════════╗") + fmt.Printf("║ \033[32m%-10s : %x\033[0m\n", "Hash", block.Hash) + fmt.Printf("║ \033[32m%-10s : %x\033[0m\n", "Prev. hash", block.PrevHash) pow := blockchain.NewProof(block) - fmt.Printf(" %-10s : %v\n", "PoW", pow.Validate()) // Blok zincirinden o bloğun proof of work değerini yazdır - fmt.Println() + fmt.Printf("║ \033[32m%-10s : %v\033[0m\n", "PoW", strconv.FormatBool(pow.Validate())) + // Blok zincirinden o bloğun proof of work değerini yazdır + for _, tx := range block.Transactions { + fmt.Println("║", tx) + } + fmt.Println("\u001B[97m╚═════════════════════════════════════════════════════════════════════════════════════════╝\n") if len(block.PrevHash) == 0 { break } + } } func (cli *CommandLine) createBlockChain(address string) { // blockchain oluşturur - chain := blockchain.InitBlockChain(address) // blockchain adında bir BlockChain nesnesi - chain.Database.Close() // blok zincirini kapat + if !wallet.ValidateAddress(address) { + log.Panic("Address is not Valid") + } + chain := blockchain.InitBlockChain(address) + chain.Database.Close() fmt.Println("Finished!") } -func (cli *CommandLine) getBalance(address string) { // bakiye almak - chain := blockchain.ContinueBlockChain(address) // blockchain adında bir BlockChain nesnesi - defer chain.Database.Close() // blok zincirini kapat +func (cli *CommandLine) getBalance(address string) { + if !wallet.ValidateAddress(address) { + log.Panic("Address is not Valid") + } + chain := blockchain.ContinueBlockChain(address) + defer chain.Database.Close() balance := 0 - UTXOs := chain.FindUTXO(address) // blok zincirinden o bloğun UTXO degerlerini al + pubKeyHash := wallet.Base58Decode([]byte(address)) + pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-4] + UTXOs := chain.FindUTXO(pubKeyHash) - for _, out := range UTXOs { // blok zincirinden o bloğun UTXO degerlerini döngürecek - balance += out.Value // blok zincirinden o bloğun UTXO degerlerinin toplamını al + for _, out := range UTXOs { + balance += out.Value } fmt.Printf("Balance of %s: %d\n", address, balance) } -func (cli *CommandLine) send(from, to string, amount int) { // para göndermek - chain := blockchain.ContinueBlockChain(from) // blockchain adında bir BlockChain nesnesi - defer chain.Database.Close() // blok zincirini kapat +func (cli *CommandLine) send(from, to string, amount int) { + if !wallet.ValidateAddress(to) { + log.Panic("Address is not Valid") + } + if !wallet.ValidateAddress(from) { + log.Panic("Address is not Valid") + } + chain := blockchain.ContinueBlockChain(from) + defer chain.Database.Close() - tx := blockchain.NewTransaction(from, to, amount, chain) // Yeni bir işlem oluştur - chain.AddBlock([]*blockchain.Transaction{tx}) // blok zincirine ekler + tx := blockchain.NewTransaction(from, to, amount, chain) + chain.AddBlock([]*blockchain.Transaction{tx}) fmt.Println("Success!") } @@ -112,11 +133,12 @@ func (cli *CommandLine) Run() { // komut satırı işlemleri createWalletCmd := flag.NewFlagSet("createwallet", flag.ExitOnError) listAddressesCmd := flag.NewFlagSet("listaddresses", flag.ExitOnError) - getBalanceAddress := getBalanceCmd.String("address", "", "Bakiye almanın adresi") // getbalance komutundaki adres bilgisini tanımla - createBlockchainAddress := createBlockchainCmd.String("address", "", "Genesis blok ödülünün gönderileceği adres") // createblockchain komutundaki adres bilgisini tanımla - sendFrom := sendCmd.String("from", "", "Kaynak cüzdan adresi") // send komutundaki kaynak adresini tanımla - sendTo := sendCmd.String("to", "", "Hedef cüzdan adresi") // send komutundaki hedef adresini tanımla - sendAmount := sendCmd.Int("amount", 0, "Gönderilecek tutar") // send komutundaki tutarı tanımla + getBalanceAddress := getBalanceCmd.String("\u001B[35maddress\u001B[0m", "", "\033[36mBakiye almanın adresi\033[0m") + createBlockchainAddress := createBlockchainCmd.String("\u001B[35maddress\u001B[0m", "", "\033[36mGenesis blok ödülünün gönderileceği adres\033[0m") + sendFrom := sendCmd.String("\u001B[35mfrom\u001B[0m", "", "\033[36mKaynak cüzdan adresi\033[0m") + sendTo := sendCmd.String("\u001B[35mto\u001B[0m", "", "\033[36mHedef cüzdan adresi\033[0m") + sendAmount := sendCmd.Int("\u001B[35mamount\u001B[0m", 0, "\033[36mGönderilecek tutar\033[0m") + // send komutundaki tutarı tanımla switch os.Args[1] { // komut satırı argümanın hangi komut oldugunu bulur case "getbalance": // getbalance komutunu çalıştır diff --git a/main.go b/main.go index ae9bec0..2269dd9 100644 --- a/main.go +++ b/main.go @@ -14,5 +14,5 @@ func main() { w := wallet.MakeWallet() w.Address() - //fmt.Print(wallet.ValidateAddress("1Dg9RoRcMYtcyj3dhXooFyjJubERMXRRwC")) + //fmt.Print(wallet.ValidateAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa")) } diff --git a/tmp/blocks/000000.vlog b/tmp/blocks/000000.vlog index 18e5008c21b8ef5d3a9db8b4021552943daf3ca0..b85447155e854a1a0f7d1a1ab7692845f3b4432a 100644 GIT binary patch literal 1522 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 diff --git a/tmp/blocks/000004.sst b/tmp/blocks/000004.sst new file mode 100644 index 0000000000000000000000000000000000000000..f81b33652be47d33ceff30c08780c3ae82f4be43 GIT binary patch literal 429 zcmZQzV9;RT{|^K}#@c+|tga}hOJ-{QpR4!&^q3puVYb@+j)3r-9?9JxH9+vsi2(|j z^uY`!1~mqL5XBn))3wQ{~)x#XJBBO z3DhS7*6yg7l$es9TBMkfnwSDr{2Ocmn9yQiU_Aj>+<-;#Ulhem`9Llg*yOc285ou` zH~`J-fGfELSAy^!ND0)7%s_<@;~8~AR;_(4K4986oDK6n;??BGo; zq1}#wfmIr=-BG6M$g8%CJHB6fns;#3v}c?AJMS!(__}z#>$=sFT}@E!e-PSj7#NsJ z;o2Lt`LC+)-V?FC;YabUCEGJz?$1blzi)f&-CK8pwS{7#+W#T6a|2!M0N1|X&}V06 z#=YAfs)uw>G)y(T$IHKG#fJcgB?OFShLFglhkU(C*K`z<&y+ozd3nE2F5c`ZEQtT}O^7#0M?j z**VYtXz|Uuk{m96gC3~%9|-NX3=HgtfgTV6g*;=8Vp3vCdTNnkMrvXTRPjepj6i@k z1A|Z`kO@(|8;j!4Fr^F(K*jv?fm|-I$uDv;Fx(CdH3lI`m=Y#YxDrI@fRymZ1C=l^ zFau-B0?cB{08)(AN^Y4sC8E>4b4&W^6GUXG5=j*dZ|&aQ5b&YnRY zj?PYwu1<~_KqZlZ=|D*!1_EcdFefm>(a|#_3#h@-$uSV99Y{Gjdb&C~dOJGW+A8TN S0WI*!PcBxnGOq>NTLJ(xLJ0l< diff --git a/tmp/blocks/MANIFEST b/tmp/blocks/MANIFEST index 4127088221a82ee66df6b5e0f740ebe278501334..12132b9fea80bf85465ebe99c286e8164a305bac 100644 GIT binary patch literal 222 zcmZ=tNiSkxU|<1a7*N}nGvorZJU^4sgF9PKpWh%Qr6+c_GWNps z52EwFH~t4|(aSgx(9WgC!6ZS1dM*|YMgc~kE;UKbU+aK&Fe@n>xNTTb+S`4L>$>qS z)9pIyoKLyzSv$>FpIEo7V(~`iZ$Q;10`9&Wfp)Nf?8r6<6MT{PL^gNBzq^7x7r#EV dIaFp_GrjV-G5f`%ULr0)JD3F+fh3avBLH%lNm~E_ literal 752 zcmZ=tNiSkxU|<1a7*La0@Wqi!g@aK^;Y3P|+*4n+O*?tR{`I7W-rQC&^UwTniFsB$ zUpN-stK$S}(c9s6ftO2-gGqu2^;|3*i~@{6U24KF&Xxh~U{+EvGn#ezhwIbA7{WN_r*pb1o-KwVk}1*<-gks&jor`ngG; zZbjRVjdbk ztG;m7YzPV12(oG8(XvjUO&lPbP9^>=xRY*gz4_tS8`3kribWagPTsFN!G77!iA4_+ z*0BO@Vh7vA2C+$^|GG8MCQc=Vm3oKD#bPHXKIrkgv+2#br6ozHzZrLLZ@4UDTW0-b zmpRC$=xH1sK%2NgHqE@NHnn8lg9}rZx|?_2+b(1;|06wn?yT6><2OZ0kGyyZw22dJ z69>d5pQ!oeK%2OMI=7dIs(iaML4LXFa^81Gf~;n_rd@o(mXg>lwoz3+ZZgOw$;=!c zpiMj=oBER9I!`rx!61CM;^Wt_QdQ&6|HB?}|17jAj^4c8-FO+$CT_4zTo9Y?)!6<5 z+Qh4*5PQ5Z|J>aVSr3&27Uld2YCQ1R>hM1Gl{z&)0yJxyl%IfXYO39)4z!66WRr?i sz_A5Zt(JM|t)+kcRwc_Ndp~?{?)>mXM~zYPpTy%pn|Q%C@dz*i06d)u?*IS* diff --git a/tmp/wallets.data b/tmp/wallets.data index 7c606c1ba249e31d19a324b9fefc3973468b4811..2a4b913eccd9f8326694269a0ff7251f0c1364a1 100644 GIT binary patch delta 459 zcmZ1~aEx<;AEVYpe`$8kfYPL#%;bqhWhzWchHkk@p=l{@?nV`Xer0CneibezrEYmf z0j`neJ}yDw8EKPw7-umt%THdxc%(i`dv>{)!rhKDdEb672{l=tv@k{Ii4$)Z7lY@H zaMtR{jEYQ>rW4!hGp;#r4|@~)x9N<`l}icD8nsjMT+1i2z5T1OkpZaY{Ua5Nd$lut z-tTf-ZOnf?`;zwxN1-?7J3RI2-}JCAo!@xfy3MvDHpq&UmEWoBL{Y{I0k*SGyZBh6=h<{$7hIcz(&8w{*gf z82$-wbr}_z<|c~GW)eRTTR7v9cIAQ(GZwkIPkEsd6Ua2%PGXL+mjMG%P15Rvyl+o> zr~XuF)~iuTe4Y`rX;;hH?Oj{+(l`{qRj+4YbiitpKay1h?NKsxNw*Bj4@&lpEJ?1+ zGET{e$j^7H%p(2U=P!XO^vAHvst8m|TC$WsMe_CG!)mQA)1NsZAP5ww$5wr)G6w{3gl7jrod@~Zu z68)T0B7KZa3qyQ8EXqp~Gt!g1LgD^e<;_r=@^)3FRa<^Web(Abe~($5u0E&d=c3-_ zdRuMv0-&1{n-|_U*0tztnx!+t>E-)`erd4}S2yflmcBYj{!7pGiy(hZIT8F%LpPI6 plVO(f*1udei`Z;tPOae2mfd&KGymM)KR|zBwMiGrDuVVf006Kza}@vp diff --git a/wallet/wallet.go b/wallet/wallet.go index 611239b..c3bdfa6 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -17,7 +17,7 @@ const ( type Wallet struct { PrivateKey ecdsa.PrivateKey //eliptik eğrisi ile private key - PublickKey []byte + PublicKey []byte } // NewKeyPair fonksiyonu, bir private ve public key olusturur @@ -60,7 +60,7 @@ func Checksum(payload []byte) []byte { // Address fonksiyonu, bir adres olusturur func (w Wallet) Address() []byte { - pubHash := PublicKeyHash(w.PublickKey) // public key hash kodu olusturulur + pubHash := PublicKeyHash(w.PublicKey) // public key hash kodu olusturulur versionedHash := append([]byte{version}, pubHash...) // version ve public key hash kodu birleştirilir checksum := Checksum(versionedHash) // checksum kodu olusturulur fullHash := append(versionedHash, checksum...) // versionedHash ve checksum kodu birleştirilir @@ -88,7 +88,7 @@ func (w Wallet) Address() []byte { // ValidateAddress fonksiyonu, bir adresin gecerli olup olmadıgını kontrol eder func ValidateAddress(address string) bool { pubKeyHash := Base58Decode([]byte(address)) // adresi byte dizisine dönüştürülür - actualChecksum := pubKeyHash[len(pubKeyHash)-checksumLength:] // checksum kodu alınır + actualChecksum := pubKeyHash[len(pubKeyHash)-checksumLength:] // checksum kodu alınır pubKeyHash[5:] 5. indeks den sona kadar oalnı alır version := pubKeyHash[0] // version kodu alınır pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-checksumLength] // version ve checksum kodu silinir targetChecksum := Checksum(append([]byte{version}, pubKeyHash...)) // checksum kodu olusturulur