How can I send transaction detail from my wallet server to blockchain server?

53 Views Asked by At

So, i run wallet_server configuaration and blockchain_server configuaration in GOland IDE. I open 127.0.0.1:5000/transactions which is the blockchain server and should show transaction data when i send address and amount from my UI that is 127.0.0.1:8080 which is the wallet server or client. But when i click send, the blockchain_server terminal says ERROR: Invalid HTTP Methods and the server tab is not updated. It remains {"transactions":[],"length":0}.this is the UI.UI with error.BLOCKCHAIN SERVER

The text in the goland terminal: For blockchain_server:

Blockchain: 2024/01/22 13:09:26 Received GET request for /transactions Blockchain: 2024/01/22 13:09:26 Private Key 90cb1de98f51758f9677e2860f81e5196b406e4911e666c61a524bb72062a46b Blockchain: 2024/01/22 13:09:26 Public Key 91749c614247897e96af2b43c30bb829ffc5b50001bc8ac35685f25ab88cb1ab50ad3b5a680d87c331fc877953be2d38b4d407e1d6ab0c9ea540fbadbc548581 Blockchain: 2024/01/22 13:09:26 blockchain_address 1CKqwRc4n91PcD2uh3aVCMYn8YcxruTPHb Blockchain: 2024/01/22 13:09:37 ERROR: Invalid HTTP Methods

For wallet_server: Wallet Server: 2024/01/22 13:09:37 Received Transaction Data: {SenderPrivateKey:0xc00008c290 SenderBlockchainAddress:0xc00008c2a0 ReceiverBlockchainAddress:0xc00008c2b0 SenderPublicKey:0xc00008c2c0 Value:0xc00008c2d0} Wallet Server: 2024/01/22 13:09:37 Response Status Code: 201 Wallet Server: 2024/01/22 13:09:37 Response Body: {"status":"success"}.

THE CODE THAT I AM USING IS CREATED BY SOMEONE ELSE. I AM COPYING IT FROM YOUTUBE TO LEARN AND PRACTICE BLOCKCHAIN AND I AM NOT CLAIMING ITS OWNERSHIP, CREDIT GOES TO THE AUTHOR.

Some parts in the video are omitted that is why i am facing this problem. I am writing the code for the relevant go files:

//wallet_server.go

package main

import (
    "Blockchain_in_GO/block"
    "Blockchain_in_GO/utility"
    "Blockchain_in_GO/wallet"
    "bytes"
    "encoding/json"
    "html/template"
    "io"
    "log"
    "net/http"
    "path"
    "strconv"
)

const tempDir = "wallet_server/templates"

type WalletServer struct {
    port    uint16
    gateway string
}

func NewWalletServer(port uint16, gateway string) *WalletServer {
    return &WalletServer{port, gateway}
}

func (ws *WalletServer) Port() uint16 {
    return ws.port
}

func (ws *WalletServer) Gateways() string {
    return ws.gateway
}

func (ws *WalletServer) Index(w http.ResponseWriter, req *http.Request) {
    switch req.Method {
    case http.MethodGet:
        t, _ := template.ParseFiles(path.Join(tempDir, "index.html"))
        t.Execute(w, "")
    default:
        log.Printf("ERROR: Invalid HTTP Method")
    }
}

func (ws *WalletServer) Wallet(w http.ResponseWriter, req *http.Request) {
    switch req.Method {
    case http.MethodPost:
        w.Header().Add("Content-Type", "application/json")
        myWallet := wallet.NewWallet()
        m, _ := myWallet.MarshalJSON()
        io.WriteString(w, string(m[:]))
    default:
        w.WriteHeader(http.StatusBadRequest)
        log.Println("ERROR: Invalid HTTP Method")
    }
}

func (ws *WalletServer) CreateTransaction(w http.ResponseWriter, req *http.Request) {
    switch req.Method {
    case http.MethodPost:
        decoder := json.NewDecoder(req.Body)
        var t wallet.TransactionRequest
        err := decoder.Decode(&t)
        if err != nil {
            log.Printf("ERROR: %v", err)
            io.WriteString(w, string(utility.JsonStatus("fail")))
            return
        }

        log.Printf("Received Transaction Data: %+v", t)

        if !t.Validate() {
            log.Println("ERROR: Missing field(s)")
            io.WriteString(w, string(utility.JsonStatus("fail")))
            return
        }

        //fmt.Println(len(*t.SenderPrivateKey))
        //fmt.Println(len(*t.SenderPublicKey))

        publicKey := utility.PublicKeyFromString(*t.SenderPublicKey)
        privateKey := utility.PrivateKeyFromString(*t.SenderPrivateKey, publicKey)

        //if *t.Value == "" {
        //log.Println("ERROR: Missing field(s)")
        //io.WriteString(w, string(utility.JsonStatus("fail")))
        //return
        //}

        value, err := strconv.ParseFloat(*t.Value, 32)
        if err != nil {
            log.Println("ERROR: Parsing Error")
            io.WriteString(w, string(utility.JsonStatus("fail")))
            return
        }
        value32 := float32(value)

        w.Header().Add("Content-Type", "application/json")

        transaction := wallet.NewTransaction(privateKey, publicKey, *t.SenderBlockchainAddress, *t.ReceiverBlockchainAddress, value32)
        signature := transaction.GenerateSignature()
        signatureStr := signature.String()

        bt := &block.TransactionRequest{SenderBlockchainAddress: t.SenderBlockchainAddress, ReceiverBlockchainAddress: t.ReceiverBlockchainAddress, SenderPublicKey: t.SenderPublicKey, Value: &value32, Signature: &signatureStr}

        m, _ := json.Marshal(bt)
        buf := bytes.NewBuffer(m)

        resp, _ := http.Post(ws.Gateways()+"/transaction", "application/json", buf)
        if resp.StatusCode == 201 {
            io.WriteString(w, string(utility.JsonStatus("success")))
            return
        }
        io.WriteString(w, string(utility.JsonStatus("fail")))
        //fmt.Println(publicKey)
        //fmt.Println(privateKey)
        //fmt.Printf("%.1f\n", value32)

        //fmt.Println(*t.SenderPublicKey)
        //fmt.Println(*t.SenderBlockchainAddress)
        //fmt.Println(*t.SenderPrivateKey)
        //fmt.Println(*t.ReceiverBlockchainAddress)
        //fmt.Println(*t.Value)

        // Send a success JSON response
        successResponse := struct {
            Status string `json:"status"`
        }{
            Status: "success",
        }

        jsonResponse, err := json.Marshal(successResponse)
        if err != nil {
            log.Printf("ERROR encoding JSON: %v", err)
            http.Error(w, "Failed to encode JSON", http.StatusInternalServerError)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        w.Write(jsonResponse)

        log.Printf("Response Status Code: %d", http.StatusCreated)
        log.Printf("Response Body: %s", jsonResponse)

    default:
        w.WriteHeader(http.StatusBadRequest)
        log.Println("ERROR: Invalid HTTP Method")
    }
}

func (ws *WalletServer) Run() {
    http.HandleFunc("/", ws.Index)
    http.HandleFunc("/wallet", ws.Wallet)
    http.HandleFunc("/transaction", ws.CreateTransaction)
    log.Fatal(http.ListenAndServe("127.0.0.1:"+strconv.Itoa(int(ws.Port())), nil))
}

//blockchain_server.go

package main

import (
    "Blockchain_in_GO/block"
    "Blockchain_in_GO/utility"
    "Blockchain_in_GO/wallet"
    "encoding/json"
    "io"
    "log"
    "net/http"
    "strconv"
)

var cache = make(map[string]*block.Blockchain)

type BlockchainServer struct {
    port uint16
}

func NewBlockchainServer(port uint16) *BlockchainServer {
    return &BlockchainServer{port}
}

func (bcs *BlockchainServer) Port() uint16 {
    return bcs.port
}

func (bcs *BlockchainServer) GetBlockchain() *block.Blockchain {
    bc, ok := cache["blockchain"]
    if !ok {
        minersWallet := wallet.NewWallet()
        bc = block.NewBlockchain(minersWallet.BlockchainAddress(), bcs.Port())
        cache["blockchain"] = bc
        log.Printf("Private Key %v", minersWallet.PrivateKeyStr())
        log.Printf("Public Key %v", minersWallet.PublicKeyStr())
        log.Printf("blockchain_address %v", minersWallet.BlockchainAddress())
    }
    return bc
}

func (bcs *BlockchainServer) GetChain(w http.ResponseWriter, req *http.Request) {
    switch req.Method {
    case http.MethodGet:
        w.Header().Add("Content-Type", "application/json")
        bc := bcs.GetBlockchain()
        m, _ := bc.MarshalJSON()
        io.WriteString(w, string(m[:]))
    default:
        log.Printf("ERROR: Invalid HTTP Methods")
    }
}

func (bcs *BlockchainServer) Transactions(w http.ResponseWriter, req *http.Request) {
    log.Printf("Received %s request for /transactions", req.Method)
    switch req.Method {
    case http.MethodGet:
        w.Header().Add("Content-Type", "application/json")
        bc := bcs.GetBlockchain()
        transactions := bc.TransactionPool()
        m, _ := json.Marshal(struct {
            Transactions []*block.Transaction `json:"transactions"`
            Length       int                  `json:"length"`
        }{
            Transactions: transactions,
            Length:       len(transactions),
        })
        io.WriteString(w, string(m[:]))
    case http.MethodPost:
        decoder := json.NewDecoder(req.Body)
        var t block.TransactionRequest
        err := decoder.Decode(&t)
        if err != nil {
            log.Printf("ERROR: %v", err)
            w.WriteHeader(http.StatusBadRequest)
            io.WriteString(w, `{"status": "fail", "message": "Invalid request"}`)
            return
        }

        if !t.Validate() {
            log.Println("ERROR: Missing Fields")
            w.WriteHeader(http.StatusBadRequest)
            io.WriteString(w, `{"status": "fail", "message": "Missing fields"}`)
            return
        }

        publicKey := utility.PublicKeyFromString(*t.SenderPublicKey)
        signature := utility.SignaturFromString(*t.Signature)
        bc := bcs.GetBlockchain()
        isCreated := bc.CreateTransaction(*t.SenderBlockchainAddress, *t.ReceiverBlockchainAddress, *t.Value, publicKey, signature)

        w.Header().Add("Content-Type", "application/json")
        if !isCreated {
            w.WriteHeader(http.StatusBadRequest)
            io.WriteString(w, `{"status": "fail", "message": "Failed to create transaction"}`)
        } else {
            w.WriteHeader(http.StatusCreated)
            io.WriteString(w, `{"status": "success", "message": "Transaction created successfully"}`)
        }

    default:
        log.Println("ERROR: Invalid HTTP Method")
        w.WriteHeader(http.StatusBadRequest)
    }
}

func (bcs *BlockchainServer) Run() {
    http.HandleFunc("/", bcs.GetChain)
    http.HandleFunc("/transactions", bcs.Transactions)
    log.Fatal(http.ListenAndServe("127.0.0.1:"+strconv.Itoa(int(bcs.Port())), nil))
}

//wallet.go

package wallet

import (
    "Blockchain_in_GO/utility"
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    "crypto/sha256"
    "encoding/json"
    "fmt"
    "github.com/btcsuite/btcutil/base58"
    "golang.org/x/crypto/ripemd160"
)

type wallet struct {
    privateKey        *ecdsa.PrivateKey
    publicKey         *ecdsa.PublicKey
    blockchainAddress string
}

// NewWallet        The following 9 steps is used to create private and public key and derive the blockchain address from public key.
//
//  Public key can also be directly used as address, but it is lengthy and undesirable as per memory utilization.
func NewWallet() *wallet {
    //1. creating ECDSA private key (32 bytes) public key (64 bytes)
    w := new(wallet)
    privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    w.privateKey = privateKey
    w.publicKey = &w.privateKey.PublicKey

    //2. perform SHA256 hashing on the public key
    h2 := sha256.New()
    h2.Write(w.publicKey.X.Bytes())
    h2.Write(w.publicKey.Y.Bytes())
    digest2 := h2.Sum(nil)

    //3. Perform RIPEMD-160 hashing on the result of SHA256 (20 bytes) (RIPEMD is used to shorten the hash)
    h3 := ripemd160.New()
    h3.Write(digest2)
    digest3 := h3.Sum(nil)

    //4. Add version byte infront of RIPEMD-160 hash (0x00 for main network)
    vd4 := make([]byte, 21) // 21 bytes because ripemd is 20 bytes and we add another 1 byte that is 0x00
    vd4[0] = 0x00
    copy(vd4[1:], digest3[:])

    //5. perform sha256 hash on the extended ripemd-160 result
    h5 := sha256.New()
    h5.Write(vd4)
    digest5 := h5.Sum(nil)

    //6. perform sha256 hash on the result of previous sha256 hash
    h6 := sha256.New()
    h6.Write(digest5)
    digest6 := h6.Sum(nil)

    //7. Take the first 4 bytes of the second sha256 hash for checksum
    chsum := digest6[:4]

    //8. Add the 4 checksum bytes from step 7 at the end of extended ripemd-160 hash from 4 (25 bytes)
    dc8 := make([]byte, 25)
    copy(dc8[:21], vd4[:])
    copy(dc8[21:], chsum[:])

    //9. Convert the result from byte string into base58
    address := base58.Encode(dc8)
    w.blockchainAddress = address
    return w
}

func (w *wallet) PrivateKey() *ecdsa.PrivateKey {
    return w.privateKey
}

func (w *wallet) PrivateKeyStr() string {
    return fmt.Sprintf("%x", w.privateKey.D.Bytes())
}

func (w *wallet) PublicKey() *ecdsa.PublicKey {
    return w.publicKey
}

func (w *wallet) PublicKeyStr() string {
    return fmt.Sprintf("%064x%064x", w.publicKey.X.Bytes(), w.publicKey.Y.Bytes())
}

func (w *wallet) BlockchainAddress() string {
    return w.blockchainAddress
}

func (w *wallet) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct {
        PrivateKey        string `json:"private_key"`
        PublicKey         string `json:"public_key"`
        BlockchainAddress string `json:"blockchain_address"`
    }{
        PrivateKey:        w.PrivateKeyStr(),
        PublicKey:         w.PublicKeyStr(),
        BlockchainAddress: w.blockchainAddress,
    })
}

type Transaction struct {
    senderPrivateKey          *ecdsa.PrivateKey
    senderPublicKey           *ecdsa.PublicKey
    senderBlockchainAddress   string
    receiverBlockchainAddress string
    value                     float32
}

func NewTransaction(privateKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey, sender string, receiver string, value float32) *Transaction {
    return &Transaction{privateKey, publicKey, sender, receiver, value}
}

// GenerateSignature In the following method we create the digital signature by using the private key of the sender and the hash of the transaction
func (t *Transaction) GenerateSignature() *utility.Signature {
    m, _ := json.Marshal(t)
    h := sha256.Sum256([]byte(m))
    r, s, _ := ecdsa.Sign(rand.Reader, t.senderPrivateKey, h[:])
    return &utility.Signature{r, s}
}

func (t *Transaction) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct { //Below we don't need to marshal senderPublicKey and senderPrivateKey because we don't need to hash them.
        Sender   string  `json:"sender_blockchain_address"`
        Receiver string  `json:"receiver_blockchain_address"`
        Value    float32 `json:"value"`
    }{
        Sender:   t.senderBlockchainAddress,
        Receiver: t.receiverBlockchainAddress,
        Value:    t.value,
    })
}

type TransactionRequest struct {
    SenderPrivateKey          *string `json:"sender_private_key"`
    SenderBlockchainAddress   *string `json:"sender_blockchain_address"`
    ReceiverBlockchainAddress *string `json:"receiver_blockchain_address"`
    SenderPublicKey           *string `json:"sender_public_key"`
    Value                     *string `json:"value"`
}

func (tr *TransactionRequest) Validate() bool {
    if tr.SenderPrivateKey == nil ||
        tr.SenderBlockchainAddress == nil ||
        tr.ReceiverBlockchainAddress == nil ||
        tr.SenderPublicKey == nil ||
        tr.Value == nil {
        return false
    }
    return true
}

//index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Wallet</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script>
        $(function () {

            $.ajax({
                url: '/wallet',
                type: 'POST',
                success: function (response) {
                    $('#public_key').val(response['public_key']);
                    $('#private_key').val(response['private_key']);
                    $('#blockchain_address').val(response['blockchain_address']);
                    console.info(response);
                },
                error: function (error) {
                    console.error(error);
                }
            });

            $('#send_money_button').click(function () {
                //var recipientAddress = $('#receiver_blockchain_address').val();
                //var amount = $('#send_amount').val();

                var confirmation = confirm("Are you sure you want to send?");
                if (!confirmation) {
                    return;
                }

                let transaction_data= {
                    'sender_private_key': $('#private_key').val(),
                    'sender_blockchain_address': $('#blockchain_address').val(),
                    'receiver_blockchain_address': $('#receiver_blockchain_address').val(),
                    'sender_public_key': $('#public_key').val(),
                    'value': $('#send_amount').val(),
                };

                $.ajax({
                    url: '/transaction',
                    type: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify(transaction_data),
                    success: function (response) {
                        console.info(response);
                        if($.parseJSON(response).message==='fail'){
                            alert('failed')
                            return
                        }
                        alert('send success')
                    },
                    error: function (response) {
                        console.error(response);
                        alert('send failed')
                    }
                });
            });
        });

    </script>
</head>
<body>

<div>
    <h1>Wallet</h1>
    <div id="wallet_amount">0</div>
    <button id="reload_wallet">Reload Wallet</button>

    <p>Public Key</p>
    <textarea id="public_key" rows="2" cols="100"></textarea>

    <p>Private Key</p>
    <textarea id="private_key" rows="1" cols="100"></textarea>

    <p>Blockchain Address</p>
    <textarea id="blockchain_address" rows="1" cols="100"></textarea>
</div>

<div>
    <h1>Send Money</h1>
    <div>
        Address: <input id="receiver_blockchain_address" size="100" type="text">
        <br>
        Amount: <input id="send_amount" type="text">
        <br>
        <button id="send_money_button">Send</button>
    </div>
</div>

</body>
</html>

//blockchain.go

package block

import (
    "Blockchain_in_GO/utility"
    "crypto/ecdsa"
    "crypto/sha256"
    "encoding/json"
    "fmt"
    "log"
    "strings"
    "time"
)

const (
    MiningDifficulty = 3 //This suggests that the first 3 characters of a string value needs to be 0. They will be
    // MINING_SENDER        anything at first, but we have to make them all 0 by some CALCULATION and thus the
    // MINING_SENDER        difficulty level suggests how difficult and long that calculation has to be.

    MiningSender = "THE BLOCKCHAIN"
    MiningReward = 1.0
)

type Block struct {
    timestamp    int64
    nonce        int
    previousHash [32]byte
    transactions []*Transaction
}

func NewBlock(nonce int, previousHash [32]byte, transactions []*Transaction) *Block {
    b := new(Block)
    b.nonce = nonce
    b.timestamp = time.Now().UnixNano()
    b.previousHash = previousHash
    b.transactions = transactions
    return b
}

// Print The following code just extends NewBlock function so that it is easier on the eyes (just for testing purpose)
func (b *Block) Print() {
    fmt.Printf("Timestamp:     %d\n", b.timestamp)
    fmt.Printf("Nonce:     %d\n", b.nonce)
    fmt.Printf("Previous Hash:     %x\n", b.previousHash)
    for _, t := range b.transactions {
        t.Print()
    }
}

func (b *Block) Hash() [32]byte {
    m, _ := json.Marshal(b) //Converting the block elements to byte
    //fmt.Println(string(m))  // printing the byte as string (just for testing)
    return sha256.Sum256(m)
}

/*Now we are going to use marshal technique because sha256 in GO does not allow
hashing for lower case variable names and even if we change the
first letter of our variable names to capital, still due to some bug
hashing is not successful.*/

func (b *Block) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct {
        Timestamp    int64          `json:"timestamp"`
        Nonce        int            `json:"nonce"`
        PreviousHash string         `json:"previous_hash"`
        Transactions []*Transaction `json:"transactions"`
    }{
        Timestamp:    b.timestamp,
        Nonce:        b.nonce,
        PreviousHash: fmt.Sprintf("%x", b.previousHash), //we rewrite it to hexadecimal numeral
        Transactions: b.transactions,
    })
}

type Blockchain struct {
    transactionPool   []*Transaction
    chain             []*Block
    blockchainAddress string
    port              uint16
}

func NewBlockchain(blockchainAddress string, port uint16) *Blockchain {
    b := &Block{}
    bc := new(Blockchain)
    bc.blockchainAddress = blockchainAddress
    bc.createBlock(0, b.Hash())
    bc.port = port
    return bc
}

func (bc *Blockchain) TransactionPool() []*Transaction {
    return bc.transactionPool
}

func (bc *Blockchain) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct {
        Blocks []*Block `json:"chains"`
    }{
        Blocks: bc.chain,
    })
}

func (bc *Blockchain) createBlock(nonce int, previousHash [32]byte) *Block {
    b := NewBlock(nonce, previousHash, bc.transactionPool) //Transfer the transaction data from pool to block
    bc.chain = append(bc.chain, b)
    bc.transactionPool = []*Transaction{} //Empty the transaction pool
    return b
}

func (bc *Blockchain) LastBlock() *Block {
    return bc.chain[len(bc.chain)-1]
}

func (bc *Blockchain) Print() {
    for i, block := range bc.chain {
        fmt.Printf("%s Chain %d %s\n", strings.Repeat("=", 25), i, strings.Repeat("=", 25))
        block.Print()
    }
    fmt.Printf("%s\n", strings.Repeat("*", 25))
}

func (bc *Blockchain) CreateTransaction(sender string, receiver string, value float32, senderPublicKey *ecdsa.PublicKey, s *utility.Signature) bool {
    isTransacted := bc.AddTransaction(sender, receiver, value, senderPublicKey, s)
    //todo
    //sync

    return isTransacted
}

func (bc *Blockchain) AddTransaction(sender string, receiver string, value float32, senderPublicKey *ecdsa.PublicKey, s *utility.Signature) bool {
    t := NewTransaction(sender, receiver, value)

    //the following suggests that if the miner is rewarded, that transaction does not need to be verified
    if sender == MiningSender {
        bc.transactionPool = append(bc.transactionPool, t)
        return true
    }

    if bc.verifyTransactionSignature(senderPublicKey, s, t) {
        if bc.CalculateTotalAmount(sender) < value {
            log.Println("ERROR: Not enough balance in the wallet")
            return false
        }
        bc.transactionPool = append(bc.transactionPool, t)
        return true
    } else {
        log.Println("ERROR: Verify Transaction")
    }
    return false
}

func (bc *Blockchain) verifyTransactionSignature(senderPublicKey *ecdsa.PublicKey, s *utility.Signature, t *Transaction) bool {
    m, _ := json.Marshal(t)
    h := sha256.Sum256(m)
    return ecdsa.Verify(senderPublicKey, h[:], s.R, s.S)
}

func (bc *Blockchain) copyTransactionPool() []*Transaction {
    transactions := make([]*Transaction, 0)
    for _, t := range bc.transactionPool {
        transactions = append(transactions, NewTransaction(t.senderBlockchainAddress, t.receiverBlockchainAddress, t.value))
    }
    return transactions
}

//The following function is to check if we have found the correct nonce

func (bc *Blockchain) validProof(nonce int, previousHash [32]byte, transactions []*Transaction, difficulty int) bool {
    zeroes := strings.Repeat("0", difficulty)
    guessBlock := Block{0, nonce, previousHash, transactions}
    guessHashStr := fmt.Sprintf("%x", guessBlock.Hash())
    //fmt.Println(guessHashStr)
    return guessHashStr[:difficulty] == zeroes
}

//The following function is to increment the nonce if we have not found the correct nonce value that satisfies the
//given challenge. (In our case, the challenge refers to making the first 3 characters as 0)

func (bc *Blockchain) proofOfWork() int {
    transactions := bc.copyTransactionPool()
    previousHash := bc.LastBlock().Hash()
    nonce := 0
    for !bc.validProof(nonce, previousHash, transactions, MiningDifficulty) {
        nonce += 1
    }
    return nonce
}

func (bc *Blockchain) Mining() bool {
    bc.AddTransaction(MiningSender, bc.blockchainAddress, MiningReward, nil, nil) // Here we have nil because rewarding after mining does not need public key and signature
    nonce := bc.proofOfWork()
    previousHash := bc.LastBlock().Hash()
    bc.createBlock(nonce, previousHash)
    log.Println("action = mining, status = success")
    return true
}

func (bc *Blockchain) CalculateTotalAmount(blockchainAddress string) float32 { //This method is used to find the balance of a node in the blockchain
    var totalAmount float32 = 0.0
    for _, b := range bc.chain {
        for _, t := range b.transactions {
            value := t.value
            if blockchainAddress == t.receiverBlockchainAddress {
                totalAmount += value
            }
            if blockchainAddress == t.senderBlockchainAddress {
                totalAmount -= value
            }
        }
    }
    return totalAmount
}

type Transaction struct {
    senderBlockchainAddress   string
    receiverBlockchainAddress string
    value                     float32
}

func NewTransaction(sender string, receiver string, value float32) *Transaction {
    return &Transaction{sender, receiver, value}
}

func (t *Transaction) Print() {
    fmt.Printf("%s\n", strings.Repeat("-", 40))
    fmt.Printf("sender_blockchain_address  %s\n", t.senderBlockchainAddress)
    fmt.Printf("reciever_blockchain_address  %s\n", t.receiverBlockchainAddress)
    fmt.Printf("value  %.1f\n", t.value)
}

func (t *Transaction) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct {
        Sender   string  `json:"sender_blockchain_address"`
        Receiver string  `json:"receiver_blockchain_address"`
        Value    float32 `json:"value"`
    }{
        Sender:   t.senderBlockchainAddress,
        Receiver: t.receiverBlockchainAddress,
        Value:    t.value,
    })
}

type TransactionRequest struct {
    SenderBlockchainAddress   *string  `json:"sender_blockchain_address"`
    ReceiverBlockchainAddress *string  `json:"receiver_blockchain_address"`
    SenderPublicKey           *string  `json:"sender_public_key"`
    Value                     *float32 `json:"value"`
    Signature                 *string  `json:"signature"`
}

func (tr *TransactionRequest) Validate() bool {
    if tr.SenderBlockchainAddress == nil ||
        tr.ReceiverBlockchainAddress == nil ||
        tr.SenderPublicKey == nil ||
        tr.Value == nil ||
        tr.Signature == nil {
        return false
    }
    return true
}

Any help will be hugely appreciated. Thank you.

I tried changing the index.html, createTransaction() method etc but no result.

0

There are 0 best solutions below