Fixing Issues

This commit is contained in:
MubarizHaroon0 2024-06-20 22:26:54 +05:00
parent ff408351a2
commit 0d2d55f839
17 changed files with 211 additions and 42 deletions

View File

@ -71,7 +71,7 @@ func CreateBlockchain(address, nodeID string) *Blockchain {
// NewBlockchain creates a new Blockchain with genesis Block // NewBlockchain creates a new Blockchain with genesis Block
func NewBlockchain(nodeID string) *Blockchain { func NewBlockchain(nodeID string) *Blockchain {
dbFile := fmt.Sprintf(dbFile, nodeID) dbFile := fmt.Sprintf(dbFile, nodeID)
if dbExists(dbFile) == false { if !dbExists(dbFile) {
fmt.Println("No existing blockchain found. Create one first.") fmt.Println("No existing blockchain found. Create one first.")
os.Exit(1) os.Exit(1)
} }
@ -81,7 +81,6 @@ func NewBlockchain(nodeID string) *Blockchain {
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }
err = db.Update(func(tx *bolt.Tx) error { err = db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(blocksBucket)) b := tx.Bucket([]byte(blocksBucket))
tip = b.Get([]byte("l")) tip = b.Get([]byte("l"))
@ -140,7 +139,7 @@ func (bc *Blockchain) FindTransaction(ID []byte) (Transaction, error) {
block := bci.Next() block := bci.Next()
for _, tx := range block.Transactions { for _, tx := range block.Transactions {
if bytes.Compare(tx.ID, ID) == 0 { if bytes.Equal(tx.ID, ID) {
return *tx, nil return *tx, nil
} }
} }
@ -181,7 +180,7 @@ func (bc *Blockchain) FindUTXO() map[string]TXOutputs {
UTXO[txID] = outs UTXO[txID] = outs
} }
if tx.IsCoinbase() == false { if !tx.IsCoinbase() {
for _, in := range tx.Vin { for _, in := range tx.Vin {
inTxID := hex.EncodeToString(in.Txid) inTxID := hex.EncodeToString(in.Txid)
spentTXOs[inTxID] = append(spentTXOs[inTxID], in.Vout) spentTXOs[inTxID] = append(spentTXOs[inTxID], in.Vout)
@ -233,7 +232,7 @@ func (bc *Blockchain) GetBlock(blockHash []byte) (Block, error) {
blockData := b.Get(blockHash) blockData := b.Get(blockHash)
if blockData == nil { if blockData == nil {
return errors.New("Block is not found.") return errors.New("Block not found ... ")
} }
block = *DeserializeBlock(blockData) block = *DeserializeBlock(blockData)
@ -272,8 +271,9 @@ func (bc *Blockchain) MineBlock(transactions []*Transaction) *Block {
for _, tx := range transactions { for _, tx := range transactions {
// TODO: ignore transaction if it's not valid // TODO: ignore transaction if it's not valid
if bc.VerifyTransaction(tx) != true { if !bc.VerifyTransaction(tx) {
log.Panic("ERROR: Invalid transaction") log.Println("ERROR: Invalid transaction passed to 'MineBlock'")
os.Exit(1)
} }
} }
@ -324,7 +324,8 @@ func (bc *Blockchain) SignTransaction(tx *Transaction, privKey ecdsa.PrivateKey)
for _, vin := range tx.Vin { for _, vin := range tx.Vin {
prevTX, err := bc.FindTransaction(vin.Txid) prevTX, err := bc.FindTransaction(vin.Txid)
if err != nil { if err != nil {
log.Panic(err) log.Println(err)
os.Exit(1)
} }
prevTXs[hex.EncodeToString(prevTX.ID)] = prevTX prevTXs[hex.EncodeToString(prevTX.ID)] = prevTX
} }
@ -343,7 +344,8 @@ func (bc *Blockchain) VerifyTransaction(tx *Transaction) bool {
for _, vin := range tx.Vin { for _, vin := range tx.Vin {
prevTX, err := bc.FindTransaction(vin.Txid) prevTX, err := bc.FindTransaction(vin.Txid)
if err != nil { if err != nil {
log.Panic(err) log.Println(err)
os.Exit(1)
} }
prevTXs[hex.EncodeToString(prevTX.ID)] = prevTX prevTXs[hex.EncodeToString(prevTX.ID)] = prevTX
} }

View File

@ -3,11 +3,13 @@ package main
import ( import (
"fmt" "fmt"
"log" "log"
"os"
) )
func (cli *CLI) createBlockchain(address, nodeID string) { func (cli *CLI) createBlockchain(address, nodeID string) {
if !ValidateAddress(address) { if !ValidateAddress(address) {
log.Panic("ERROR: Address is not valid") log.Println("ERROR: Address is not valid")
os.Exit(1)
} }
bc := CreateBlockchain(address, nodeID) bc := CreateBlockchain(address, nodeID)
defer bc.db.Close() defer bc.db.Close()

View File

@ -3,12 +3,15 @@ package main
import ( import (
"fmt" "fmt"
"log" "log"
"os"
) )
func (cli *CLI) getBalance(address, nodeID string) { func (cli *CLI) getBalance(address, nodeID string) {
if !ValidateAddress(address) { if !ValidateAddress(address) {
log.Panic("ERROR: Address is not valid") log.Println("ERROR: Address is not valid")
os.Exit(1)
} }
bc := NewBlockchain(nodeID) bc := NewBlockchain(nodeID)
UTXOSet := UTXOSet{bc} UTXOSet := UTXOSet{bc}
defer bc.db.Close() defer bc.db.Close()

View File

@ -13,6 +13,6 @@ func (cli *CLI) listAddresses(nodeID string) {
addresses := wallets.GetAddresses() addresses := wallets.GetAddresses()
for _, address := range addresses { for _, address := range addresses {
fmt.Println(address) fmt.Printf("Address : %s\n", address)
} }
} }

View File

@ -17,6 +17,7 @@ func (cli *CLI) printChain(nodeID string) {
fmt.Printf("============ Block %x ============\n", block.Hash) fmt.Printf("============ Block %x ============\n", block.Hash)
fmt.Printf("Height: %d\n", block.Height) fmt.Printf("Height: %d\n", block.Height)
fmt.Printf("Prev. block: %x\n", block.PrevBlockHash) fmt.Printf("Prev. block: %x\n", block.PrevBlockHash)
fmt.Printf("Merkle Root: %x\n", block.HashTransactions())
pow := NewProofOfWork(block) pow := NewProofOfWork(block)
fmt.Printf("PoW: %s\n\n", strconv.FormatBool(pow.Validate())) fmt.Printf("PoW: %s\n\n", strconv.FormatBool(pow.Validate()))
for _, tx := range block.Transactions { for _, tx := range block.Transactions {

View File

@ -3,16 +3,23 @@ package main
import ( import (
"fmt" "fmt"
"log" "log"
"os"
) )
func (cli *CLI) send(from, to string, amount int, nodeID string, mineNow bool) { func (cli *CLI) send(from, to string, amount int, nodeID string, mineNow bool) {
if !ValidateAddress(from) { if !ValidateAddress(from) {
log.Panic("ERROR: Sender address is not valid") log.Println("ERROR: Sender address is not valid")
os.Exit(1)
} }
if !ValidateAddress(to) { if !ValidateAddress(to) {
log.Panic("ERROR: Recipient address is not valid") log.Println("ERROR: Recipient address is not valid")
os.Exit(1)
} }
if from == to {
log.Println("ERROR: Sender and Recipient cannot be same")
os.Exit(1)
}
bc := NewBlockchain(nodeID) bc := NewBlockchain(nodeID)
UTXOSet := UTXOSet{bc} UTXOSet := UTXOSet{bc}
defer bc.db.Close() defer bc.db.Close()
@ -26,12 +33,15 @@ func (cli *CLI) send(from, to string, amount int, nodeID string, mineNow bool) {
tx := NewUTXOTransaction(&wallet, to, amount, &UTXOSet) tx := NewUTXOTransaction(&wallet, to, amount, &UTXOSet)
if mineNow { if mineNow {
cbTx := NewCoinbaseTX(from, "") cbTx := NewCoinbaseTX(from, "")
txs := []*Transaction{cbTx, tx} txs := []*Transaction{cbTx, tx}
newBlock := bc.MineBlock(txs) newBlock := bc.MineBlock(txs)
UTXOSet.Update(newBlock) UTXOSet.Update(newBlock)
} else { } else {
sendTx(knownNodes[0], tx) sendTx(knownNodes[0], tx)
} }

16
go.mod Normal file
View File

@ -0,0 +1,16 @@
module blockchain_go
go 1.22.4
require (
github.com/boltdb/bolt v1.3.1
github.com/stretchr/testify v1.9.0
golang.org/x/crypto v0.24.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

16
go.sum Normal file
View File

@ -0,0 +1,16 @@
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0
logic.txt Normal file
View File

View File

@ -51,14 +51,12 @@ func (pow *ProofOfWork) Run() (int, []byte) {
var hash [32]byte var hash [32]byte
nonce := 0 nonce := 0
fmt.Printf("Mining a new block") fmt.Printf("Mining a new block ")
for nonce < maxNonce { for nonce < maxNonce {
data := pow.prepareData(nonce) data := pow.prepareData(nonce)
hash = sha256.Sum256(data) hash = sha256.Sum256(data)
if math.Remainder(float64(nonce), 100000) == 0 {
fmt.Printf("\r%x", hash)
}
hashInt.SetBytes(hash[:]) hashInt.SetBytes(hash[:])
if hashInt.Cmp(pow.target) == -1 { if hashInt.Cmp(pow.target) == -1 {
@ -67,8 +65,8 @@ func (pow *ProofOfWork) Run() (int, []byte) {
nonce++ nonce++
} }
} }
fmt.Print("\n\n")
fmt.Printf("Nonce found: %d\n", nonce)
return nonce, hash[:] return nonce, hash[:]
} }

View File

@ -203,7 +203,7 @@ func handleBlock(request []byte, bc *Blockchain) {
bc.AddBlock(block) bc.AddBlock(block)
fmt.Printf("Added block %x\n", block.Hash) fmt.Printf("Added block %x\n", block.Hash)
fmt.Printf("Merkle root %x\n", block.HashTransactions())
if len(blocksInTransit) > 0 { if len(blocksInTransit) > 0 {
blockHash := blocksInTransit[0] blockHash := blocksInTransit[0]
sendGetData(payload.AddrFrom, "block", blockHash) sendGetData(payload.AddrFrom, "block", blockHash)
@ -421,7 +421,9 @@ func handleConnection(conn net.Conn, bc *Blockchain) {
func StartServer(nodeID, minerAddress string) { func StartServer(nodeID, minerAddress string) {
nodeAddress = fmt.Sprintf("localhost:%s", nodeID) nodeAddress = fmt.Sprintf("localhost:%s", nodeID)
miningAddress = minerAddress miningAddress = minerAddress
ln, err := net.Listen(protocol, nodeAddress) ln, err := net.Listen(protocol, nodeAddress)
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }
@ -440,6 +442,7 @@ func StartServer(nodeID, minerAddress string) {
} }
go handleConnection(conn, bc) go handleConnection(conn, bc)
} }
} }
func gobEncode(data interface{}) []byte { func gobEncode(data interface{}) []byte {

View File

@ -163,7 +163,7 @@ func (tx *Transaction) Verify(prevTXs map[string]Transaction) bool {
dataToVerify := fmt.Sprintf("%x\n", txCopy) dataToVerify := fmt.Sprintf("%x\n", txCopy)
rawPubKey := ecdsa.PublicKey{Curve: curve, X: &x, Y: &y} rawPubKey := ecdsa.PublicKey{Curve: curve, X: &x, Y: &y}
if ecdsa.Verify(&rawPubKey, []byte(dataToVerify), &r, &s) == false { if !ecdsa.Verify(&rawPubKey, []byte(dataToVerify), &r, &s) {
return false return false
} }
txCopy.Vin[inID].PubKey = nil txCopy.Vin[inID].PubKey = nil
@ -173,6 +173,7 @@ func (tx *Transaction) Verify(prevTXs map[string]Transaction) bool {
} }
// NewCoinbaseTX creates a new coinbase transaction // NewCoinbaseTX creates a new coinbase transaction
func NewCoinbaseTX(to, data string) *Transaction { func NewCoinbaseTX(to, data string) *Transaction {
if data == "" { if data == "" {
randData := make([]byte, 20) randData := make([]byte, 20)
@ -197,35 +198,43 @@ func NewUTXOTransaction(wallet *Wallet, to string, amount int, UTXOSet *UTXOSet)
var inputs []TXInput var inputs []TXInput
var outputs []TXOutput var outputs []TXOutput
// Get the public key hash of the wallet
pubKeyHash := HashPubKey(wallet.PublicKey) pubKeyHash := HashPubKey(wallet.PublicKey)
acc, validOutputs := UTXOSet.FindSpendableOutputs(pubKeyHash, amount)
// Find spendable outputs for the given amount
acc, validOutputs := UTXOSet.FindSpendableOutputs(pubKeyHash, amount)
if acc < amount { if acc < amount {
log.Panic("ERROR: Not enough funds") log.Panic("ERROR: Not enough funds")
} }
// Build a list of inputs // Build a list of inputs from the valid outputs
for txid, outs := range validOutputs { for txid, outs := range validOutputs {
txID, err := hex.DecodeString(txid) txID, err := hex.DecodeString(txid)
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }
for _, out := range outs { for _, outIndex := range outs {
input := TXInput{txID, out, nil, wallet.PublicKey} input := TXInput{txID, outIndex, nil, wallet.PublicKey}
inputs = append(inputs, input) inputs = append(inputs, input)
} }
} }
// Build a list of outputs // Create an output for the recipient
from := fmt.Sprintf("%s", wallet.GetAddress())
outputs = append(outputs, *NewTXOutput(amount, to)) outputs = append(outputs, *NewTXOutput(amount, to))
// Create a change output if there is any change
if acc > amount { if acc > amount {
outputs = append(outputs, *NewTXOutput(acc-amount, from)) // a change changeAddress := fmt.Sprintf("%s", wallet.GetAddress())
outputs = append(outputs, *NewTXOutput(acc-amount, changeAddress)) // change output
} }
// Create the transaction
tx := Transaction{nil, inputs, outputs} tx := Transaction{nil, inputs, outputs}
tx.ID = tx.Hash() tx.ID = tx.Hash()
// Sign the transaction
UTXOSet.Blockchain.SignTransaction(&tx, wallet.PrivateKey) UTXOSet.Blockchain.SignTransaction(&tx, wallet.PrivateKey)
return &tx return &tx

View File

@ -14,5 +14,5 @@ type TXInput struct {
func (in *TXInput) UsesKey(pubKeyHash []byte) bool { func (in *TXInput) UsesKey(pubKeyHash []byte) bool {
lockingHash := HashPubKey(in.PubKey) lockingHash := HashPubKey(in.PubKey)
return bytes.Compare(lockingHash, pubKeyHash) == 0 return bytes.Equal(lockingHash, pubKeyHash)
} }

View File

@ -21,7 +21,7 @@ func (out *TXOutput) Lock(address []byte) {
// IsLockedWithKey checks if the output can be used by the owner of the pubkey // IsLockedWithKey checks if the output can be used by the owner of the pubkey
func (out *TXOutput) IsLockedWithKey(pubKeyHash []byte) bool { func (out *TXOutput) IsLockedWithKey(pubKeyHash []byte) bool {
return bytes.Compare(out.PubKeyHash, pubKeyHash) == 0 return bytes.Equal(out.PubKeyHash, pubKeyHash)
} }
// NewTXOutput create a new TXOutput // NewTXOutput create a new TXOutput

View File

@ -2,6 +2,7 @@ package main
import ( import (
"encoding/hex" "encoding/hex"
"fmt"
"log" "log"
"github.com/boltdb/bolt" "github.com/boltdb/bolt"
@ -29,9 +30,16 @@ func (u UTXOSet) FindSpendableOutputs(pubkeyHash []byte, amount int) (int, map[s
outs := DeserializeOutputs(v) outs := DeserializeOutputs(v)
for outIdx, out := range outs.Outputs { for outIdx, out := range outs.Outputs {
if out.IsLockedWithKey(pubkeyHash) && accumulated < amount { if out.IsLockedWithKey(pubkeyHash) {
accumulated += out.Value if accumulated < amount {
unspentOutputs[txID] = append(unspentOutputs[txID], outIdx) accumulated += out.Value
unspentOutputs[txID] = append(unspentOutputs[txID], outIdx)
// Early exit if the required amount is accumulated
if accumulated >= amount {
return nil
}
}
} }
} }
} }
@ -42,6 +50,11 @@ func (u UTXOSet) FindSpendableOutputs(pubkeyHash []byte, amount int) (int, map[s
log.Panic(err) log.Panic(err)
} }
// Check if we were able to accumulate the required amount
if accumulated < amount {
log.Printf("Warning: Unable to find enough spendable outputs. Needed %d, found %d", amount, accumulated)
}
return accumulated, unspentOutputs return accumulated, unspentOutputs
} }
@ -50,13 +63,20 @@ func (u UTXOSet) FindUTXO(pubKeyHash []byte) []TXOutput {
var UTXOs []TXOutput var UTXOs []TXOutput
db := u.Blockchain.db db := u.Blockchain.db
// Read-only transaction to view the database
err := db.View(func(tx *bolt.Tx) error { err := db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(utxoBucket)) b := tx.Bucket([]byte(utxoBucket))
if b == nil {
return fmt.Errorf("Bucket %s not found!", utxoBucket)
}
c := b.Cursor() c := b.Cursor()
// Iterate through all keys in the bucket
for k, v := c.First(); k != nil; k, v = c.Next() { for k, v := c.First(); k != nil; k, v = c.Next() {
outs := DeserializeOutputs(v) outs := DeserializeOutputs(v)
// Filter outputs that are locked with the given public key hash
for _, out := range outs.Outputs { for _, out := range outs.Outputs {
if out.IsLockedWithKey(pubKeyHash) { if out.IsLockedWithKey(pubKeyHash) {
UTXOs = append(UTXOs, out) UTXOs = append(UTXOs, out)
@ -119,7 +139,7 @@ func (u UTXOSet) Reindex() {
UTXO := u.Blockchain.FindUTXO() UTXO := u.Blockchain.FindUTXO()
err = db.Update(func(tx *bolt.Tx) error { _ = db.Update(func(tx *bolt.Tx) error {
b := tx.Bucket(bucketName) b := tx.Bucket(bucketName)
for txID, outs := range UTXO { for txID, outs := range UTXO {
@ -147,7 +167,7 @@ func (u UTXOSet) Update(block *Block) {
b := tx.Bucket([]byte(utxoBucket)) b := tx.Bucket([]byte(utxoBucket))
for _, tx := range block.Transactions { for _, tx := range block.Transactions {
if tx.IsCoinbase() == false { if !tx.IsCoinbase() {
for _, vin := range tx.Vin { for _, vin := range tx.Vin {
updatedOuts := TXOutputs{} updatedOuts := TXOutputs{}
outsBytes := b.Get(vin.Txid) outsBytes := b.Get(vin.Txid)
@ -175,10 +195,7 @@ func (u UTXOSet) Update(block *Block) {
} }
newOutputs := TXOutputs{} newOutputs := TXOutputs{}
for _, out := range tx.Vout { newOutputs.Outputs = append(newOutputs.Outputs, tx.Vout...)
newOutputs.Outputs = append(newOutputs.Outputs, out)
}
err := b.Put(tx.ID, newOutputs.Serialize()) err := b.Put(tx.ID, newOutputs.Serialize())
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)

View File

@ -6,7 +6,10 @@ import (
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/sha256" "crypto/sha256"
"encoding/gob"
"fmt"
"log" "log"
"math/big"
"golang.org/x/crypto/ripemd160" "golang.org/x/crypto/ripemd160"
) )
@ -63,7 +66,7 @@ func ValidateAddress(address string) bool {
pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-addressChecksumLen] pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-addressChecksumLen]
targetChecksum := checksum(append([]byte{version}, pubKeyHash...)) targetChecksum := checksum(append([]byte{version}, pubKeyHash...))
return bytes.Compare(actualChecksum, targetChecksum) == 0 return bytes.Equal(actualChecksum, targetChecksum)
} }
// Checksum generates a checksum for a public key // Checksum generates a checksum for a public key
@ -84,3 +87,84 @@ func newKeyPair() (ecdsa.PrivateKey, []byte) {
return *private, pubKey return *private, pubKey
} }
func (w *Wallet) GobEncode() ([]byte, error) {
var buffer bytes.Buffer
encoder := gob.NewEncoder(&buffer)
// Encode the curve name
curveName := "P256"
if err := encoder.Encode(curveName); err != nil {
return nil, err
}
// Encode the private key components
privateKeyBytes := w.PrivateKey.D.Bytes()
if err := encoder.Encode(privateKeyBytes); err != nil {
return nil, err
}
// Encode the public key components
xBytes := w.PrivateKey.PublicKey.X.Bytes()
yBytes := w.PrivateKey.PublicKey.Y.Bytes()
if err := encoder.Encode(xBytes); err != nil {
return nil, err
}
if err := encoder.Encode(yBytes); err != nil {
return nil, err
}
// Encode the public key
if err := encoder.Encode(w.PublicKey); err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
func (w *Wallet) GobDecode(data []byte) error {
buffer := bytes.NewBuffer(data)
decoder := gob.NewDecoder(buffer)
// Decode the curve name
var curveName string
if err := decoder.Decode(&curveName); err != nil {
return err
}
// Set the curve based on the name
var curve elliptic.Curve
switch curveName {
case "P256":
curve = elliptic.P256()
default:
return fmt.Errorf("unsupported curve: %s", curveName)
}
// Decode the private key components
var privateKeyBytes []byte
if err := decoder.Decode(&privateKeyBytes); err != nil {
return err
}
w.PrivateKey.PublicKey.Curve = curve
w.PrivateKey.D = new(big.Int).SetBytes(privateKeyBytes)
// Decode the public key components
var xBytes, yBytes []byte
if err := decoder.Decode(&xBytes); err != nil {
return err
}
if err := decoder.Decode(&yBytes); err != nil {
return err
}
w.PrivateKey.PublicKey.X = new(big.Int).SetBytes(xBytes)
w.PrivateKey.PublicKey.Y = new(big.Int).SetBytes(yBytes)
// Decode the public key
if err := decoder.Decode(&w.PublicKey); err != nil {
return err
}
return nil
}

View File

@ -66,7 +66,7 @@ func (ws *Wallets) LoadFromFile(nodeID string) error {
} }
var wallets Wallets var wallets Wallets
gob.Register(elliptic.P256()) //gob.Register(elliptic.P256())
decoder := gob.NewDecoder(bytes.NewReader(fileContent)) decoder := gob.NewDecoder(bytes.NewReader(fileContent))
err = decoder.Decode(&wallets) err = decoder.Decode(&wallets)
if err != nil { if err != nil {
@ -80,17 +80,25 @@ func (ws *Wallets) LoadFromFile(nodeID string) error {
// SaveToFile saves wallets to a file // SaveToFile saves wallets to a file
func (ws Wallets) SaveToFile(nodeID string) { func (ws Wallets) SaveToFile(nodeID string) {
// Create a buffer to hold the serialized data
var content bytes.Buffer var content bytes.Buffer
// Format the filename using the nodeID
walletFile := fmt.Sprintf(walletFile, nodeID) walletFile := fmt.Sprintf(walletFile, nodeID)
// Register the elliptic curve with the gob package
gob.Register(elliptic.P256()) gob.Register(elliptic.P256())
// Create a new encoder that writes to the buffer
encoder := gob.NewEncoder(&content) encoder := gob.NewEncoder(&content)
// Encode the Wallets object into the buffer
err := encoder.Encode(ws) err := encoder.Encode(ws)
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)
} }
// Write the buffer's content to the file
err = ioutil.WriteFile(walletFile, content.Bytes(), 0644) err = ioutil.WriteFile(walletFile, content.Bytes(), 0644)
if err != nil { if err != nil {
log.Panic(err) log.Panic(err)