Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

C++ Programming excercise Create two files: Miner.h (class definition) and Miner

ID: 3868587 • Letter: C

Question

C++ Programming excercise

Create two files: Miner.h (class definition) and Miner.cpp (class implementation)
and use the UML below to guide your implementation.
Miner
- name : string
- currentBlock : Block*
- wallet : Wallet*
- blockReward : float
+ Miner():
+ Miner(n: string):
+ ~Miner():
+ setName(n: string): void
+ getName(): string
+ createBlock(p: Transaction**, prev: Block*, reward: float): void
+ getBlock(): Block*
+ deleteBlock(): void
+ confirmBlock(): void
+ getWallet(): Wallet*
+ mine(nonce : int): string
Member Variables:
• name - the name of an individual miner or a group of miners. This can also
be left blank as some miners wish to remain anonymous.
• currentBlock - a pointer to a Block object that a miner is currently mining
or has just created
• wallet - a pointer to a Wallet object which contains the account details of
the miner, through which he/she can be paid his/her mining reward.
• blockReward - the amount that the miner gets for confirming a block. It is
first set to zero and gets updated with every mining call.
Member Functions:
• The Miner has a default constructor which initializes the miner’s name to
an empty string and the blockReward to zero. It also has a constructor

which initializes the miner’s name to the given input parameter. Both constructors
dynamically create a Wallet object and initialize the currentBlock
object to a null pointer.
• ~Miner() - should free memory used for the current block (possibly through
the deleteBlock() function) and the wallet.
• setName(string n) and getName() - sets and retrieves the name of the miner
• createBlock(Transaction** p, Block* prev, float reward) - accepts onedimensional
dynamic array with Transaction* objects, a Block pointer to
the previous block (i.e. the last block in the blockchain) and the amount of
the reward for mining the block.
The process of creating a block is as follows:
1. Check if memory for the current block has been allocated already, if
so, release the memory.
2. Instantiate a new Block object.
3. Check if the pointer to a previous block is defined (i.e. not a null
pointer), if so, the current block’s id should be an increment of the
previous block’s id, and store the previous block’s hash value
4. The miner should add a reward transaction to himself as the first
transaction in the block. The fromAddress of the transaction should be
empty.
5. The miner should then add as many transactions from the transaction
pool as the block allows. Before adding, first check that the pointer
to a transaction in a pool is not null (this is because transactions in
the pool that have been confirmed and added to the blockchain are
deallocated).
6. Update the removeFromPool status of a pool transaction to indicate
that it can now be removed from the pool.
• getBlock() - returns a pointer to the current block
• deleteBlock() - deallocates the memory of the current block. If your implementation
is correct, this should automatically call the destructors of
any Transaction objects in the block.
• confirmBlock() - serves to mark the current block as confirmed (it should
call the relevant block function that modifies this status). It is at this point
that the miner can send the reward to his wallet.
• getWallet() - returns the miner’s wallet.
• mine(int nonce) - computes the block’s hash value based on the transaction
ID hashes, the previous block’s hash value and the nonce value. All

these components are joined using hyphens (-) and the result has a format
similar to the one shown in the image below (prior to undergoing the final
hash), where 163 is the input nonce value.

Explanation / Answer

main.cpp
-------------------------------------------
#include <iostream>
#include <string>

#include "Simulator.h"

int main()
{
    cout << "-------------------------------------------------- ";
    cout << " Simulation ";
    cout << "-------------------------------------------------- ";

    int numMiners, randomSeed;
    string *minerNames, inputFileName;

    cout << "Enter the number of miners: ";
    cin >> numMiners;
    cin.ignore();

    minerNames = new string[numMiners];

    for (int a=0; a<numMiners; a++)
    {
        cout << "Enter the name of miner " << a+1 << ": ";
        getline(cin, minerNames[a]);
    }

    cout << "Enter the transactions filename: ";
    cin >> inputFileName;

    cout << "Enter a positive seed number: ";
    cin >> randomSeed;
    srand(randomSeed);

    cout << endl;

    Simulator btcSim(inputFileName, minerNames, numMiners);

    btcSim.run(300);

    delete [] minerNames;

    return 0;
}
--------------------------------------------------------------
Miner.cpp
-------------------------
#include <iostream>

#include "Miner.h"
#include "Wallet.h"
#include "Crypto.h"
#include "Block.h"
#include "Transaction.h"

using namespace std;

Miner::Miner()
{
   name = "";
   currentBlock = nullptr;
   wallet = new Wallet;
   blockReward = 0;
}

Miner::Miner(string n)
{
   name = n;
   currentBlock = nullptr;
   wallet = new Wallet;
   blockReward = 0;
}

Miner::~Miner()
{
   if (currentBlock!=nullptr)
       delete currentBlock;

   delete wallet;
}

void Miner::setName(string n)
{
   name = n;
}

string Miner::getName()
{
   return name;
}

void Miner::createBlock(Transaction **p, Block *prev, float reward)
{
   if (currentBlock!=nullptr)
   {
       deleteBlock();
   }
   else
   {
       if (prev!=nullptr)
       {
           currentBlock = new Block(prev->getId()+1, prev->getBlockHash(), name);
       }
       else
       {
           currentBlock = new Block(1, "", name);
       }
   }

   currentBlock->addTransaction("", wallet->getAddress(), name, reward);
   blockReward = reward;

   int a=0;

   do
   {
       if (p[a]!=nullptr)
       {
           currentBlock->addTransaction(p[a]);
           p[a]->setRemoveFromPool(true);
       }

       a++;

   } while (currentBlock->canAddTransaction());
}

Block *Miner::getBlock()
{
   return currentBlock;
}

void Miner::deleteBlock()
{
   delete currentBlock;
   currentBlock = nullptr;
}

void Miner::confirmBlock()
{
   currentBlock->confirm();
   wallet->deposit(blockReward);
}

Wallet *Miner::getWallet()
{
   return wallet;
}

string Miner::mine(int nonce)
{
   string output="";
   Crypto temp;

   for (int a=0; a<currentBlock->getNumTransactions(); a++)
   {
       output += (temp.sha1hash((currentBlock->getTransaction(a))->getId())+"-");
   }

   output += (currentBlock->getPreviousBlockHash()+"-"+to_string(nonce));

   currentBlock->setBlockHash(temp.sha1hash(output));

   return currentBlock->getBlockHash();

}
---------------------------------------------------
Miner.h
--------------------------------
#ifndef MINER_H
#define MINER_H

#include <string>

#include "Wallet.h"
#include "Block.h"
#include "Transaction.h"

using namespace std;

class Miner
{
private:
    string name;
    Block *currentBlock;
    Wallet *wallet;
    float blockReward;

public:
    Miner();
    Miner(string n);
    ~Miner();
    void setName(string n);
    string getName();
    void createBlock(Transaction **p, Block *prev, float reward);
    Block *getBlock();
    void deleteBlock();
    void confirmBlock();
    Wallet *getWallet();
    string mine(int nonce);

};

#endif
---------------------------------------------------------------
Transaction.cpp
-------------------------------
#include <string>

#include "Transaction.h"

using namespace std;

int Transaction::numTransactions = 1;

Transaction::Transaction(string f, string t, string s, float a)
{
    fromAddress = f;
    toAddress = t;
    signature = s;
    amount = a;

    id = numTransactions;
    confirmed = false;
    removeFromPool = false;

    numTransactions++;
}

Transaction::Transaction(Transaction& other)
{
    id = other.id;
    amount = other.amount;
    fromAddress = other.fromAddress;
    toAddress = other.toAddress;
    signature = other.signature;
    confirmed = other.confirmed;
    removeFromPool = other.removeFromPool;
}

int Transaction::getId()
{
    return id;
}

float Transaction::getAmount()
{
    return amount;
}

string Transaction::getRecipientAddress()
{
    return toAddress;
}

string Transaction::getSenderAddress()
{
    return fromAddress;
}

string Transaction::getSignature()
{
    return signature;
}

void Transaction::confirm()
{
    confirmed = true;
}

bool Transaction::isConfirmed()
{
    return confirmed;
}

void Transaction::setRemoveFromPool(bool r)
{
    removeFromPool = r;
}

bool Transaction::shouldRemoveFromPool()
{
    return removeFromPool;
}
-------------------------------------------------------
Transaction.h
-------------------------
#ifndef TRANSACTIONS_H
#define TRANSACTIONS_H

#include <string>

using namespace std;

class Transaction
{
private:
    int id;
    float amount;
    string fromAddress;
    string toAddress;
    string signature;
    bool confirmed;
    bool removeFromPool;

    static int numTransactions;

public:
    Transaction(string f, string t, string s, float a);
    Transaction(Transaction& other);
    int getId();
    float getAmount();
    string getRecipientAddress();
    string getSenderAddress();
    string getSignature();
    void confirm();
    bool isConfirmed();
    void setRemoveFromPool(bool r);
    bool shouldRemoveFromPool();

};

#endif
--------------------------------------------------------------------------
Wallet.cpp
------------------------------
#include <iostream>
#include <string>

#include "Wallet.h"
#include "Crypto.h"

using namespace std;

void Wallet::generateAddress()
{
    address = Crypto::strtohex(Crypto::random_string(10));
}

void Wallet::generateSignature()
{
    signature = Crypto::sha1hash(Crypto::random_string(20));
}

Wallet::Wallet()
{
    balance = 0;
    generateAddress();
    generateSignature();
}

string Wallet::getAddress()
{
    return address;
}

string Wallet::getSignature()
{
    return signature;
}

void Wallet::deposit(float v)
{
    balance += v;
}

void Wallet::withdraw(float v)
{
    balance -= v;
}

float Wallet::getBalance()
{
    return balance;
}
----------------------------------------------------------
Wallet.h
------------------------
#ifndef WALLET_H
#define WALLET_H

#include <string>

using namespace std;

class Wallet
{
private:
    float balance;
    string address;
    string signature;

    void generateAddress();
    void generateSignature();

public:
    Wallet();
    string getAddress();
    string getSignature();
    void deposit(float v);
    void withdraw(float v);
    float getBalance();

};

#endif
--------------------------------------------------------------------
Simulator
--------------------------
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>

#include "Simulator.h"
#include "Block.h"

using namespace std;

Simulator::Simulator(string txfile, string minerNames[], int nMiners)
{
    pool = nullptr;
    miners = nullptr;
    blockchain = nullptr;

    numTx = 0;
    numBlocks = 0;
    numMiners = nMiners;

    loadTxPool(txfile);
    initMiners(minerNames);
    initBlockchain();
}

Simulator::~Simulator()
{
    if (pool){
        for(int i=0; i < numTx; i++)
            delete pool[i];
        delete [] pool;
        pool = nullptr;
    }

    if (miners) {
        for (int i=0; i < numMiners; i++)
            delete miners[i];
        delete [] miners;
        miners = nullptr;
    }

    if (blockchain) {
        for (int i=0; i < numBlocks; i++)
            delete blockchain[i];
        delete [] blockchain;
        blockchain = nullptr;
    }
}

void Simulator::loadTxPool(string filename)
{
    ifstream file(filename);
    string line, fromAddress, toAddress, signature;
    float amount;

    int i=0;
    if (file)
    {
        //first line of the file contains the number of transactions
        getline(file, line);
        istringstream ss(line);
        ss >> numTx;

        //initialize the Transaction pool dynamic array
        pool = new Transaction*[numTx];

        //read the rest of the lines and create corresponding Transaction objects
        getline(file, line);
        while (file)
        {
            istringstream ss(line);
            ss >> fromAddress >> amount >> toAddress >> signature;
            pool[i] = new Transaction(fromAddress, toAddress, signature, amount);

            i++;
            getline(file, line);
        }
    }
    file.close();
}

void Simulator::initBlockchain()
{
    //Write code to initialize the blockchain dynamic array
    //Determine the number of blocks based on the number of transactions in the pool
    //(i.e. how many blocks will it require to store all these transactions?)
    //Hint: Don't forget to count the miner reward transactions in your block calculation

    int count = numTx/4;

    if (count*4<numTx)
        count++;

    numBlocks = count;
    blockchain = new Block*[numBlocks];

}

void Simulator::initMiners(string names[])
{
    //Write code to initialize the miners dynamic array and
    // instantiate the dynamic Miner objects

    miners = new Miner*[numMiners];

    for (int a=0; a<numMiners; a++)
        miners[a] = new Miner(names[a]);

}

void Simulator::removeMinedTxFromPool()
{
    //check if transactions have been marked for removal from pool, if so
    //deallocate the memory of the affected transactions

    for (int a=0; a<numTx; a++)
    {
        if (pool[a]!=nullptr && pool[a]->shouldRemoveFromPool())
        {
            delete pool[a];
            pool[a] = nullptr;
        }
    }

}

int Simulator::getUnminedTxCount()
{
    //get the number of transactions in the pool that have not been removed from the pool
    //(still un-mined/unprocessed)
    int count = 0;

    for (int a=0; a<numTx; a++)
    {
        if (!pool[a]->shouldRemoveFromPool())
        {
            count++;
        }
    }

    return count;
}

bool Simulator::checkHash(string hash)
{
    //check if the first 2 characters of the hash are the same as the target
    //and return true if that's the case
    bool targetMet = false;

    if (hash[0]==MINING_TARGET[0] && hash[1]==MINING_TARGET[1])
    {
        targetMet = true;
    }

    return targetMet;
}

void Simulator::run(int maxIters)
{
    //follow the instructions in the assignment to complete this function

    for (int a=0; a<numBlocks; a++)
    {
        int nonce = 0;
        bool mined=false;
        int index;

        for (int b=0; b<numMiners; b++)
        {
            if (a==0)
                miners[b]->createBlock(pool, nullptr, 12.5);
            else
                miners[b]->createBlock(pool, blockchain[a-1], 12.5);
        }

        do
        {
            for (int b=0; b<numMiners; b++)
            {
                if (checkHash(miners[b]->mine(nonce)))
                {
                    mined = true;
                    index = b;
                    break;
                }
            }

            nonce++;

        } while(!mined && nonce<maxIters);

        miners[index]->confirmBlock();
        blockchain[a] = new Block(*miners[index]->getBlock());

        cout << "Block " << a+1 << " mined by " << miners[index]->getName();
        cout << " with nonce " << nonce;
        cout << " (block hash: " << blockchain[a]->getBlockHash() << ") ";

        for (int b=0; b<numMiners; b++)
            miners[b]->deleteBlock();

        removeMinedTxFromPool();
    }

    cout << " Blockchain Printout: ";
    cout << "======================================================= ";

    for (int a=0; a<numBlocks; a++)
    {
        blockchain[a]->printBlockSummary();
        cout << endl;
    }

    cout << "Blockchain Printout: ";
    cout << "============================== ";

    for (int a=0; a<numMiners; a++)
    {
        cout << miners[a]->getName() << setw(20) << "BTC ";
        cout << setprecision(3) << fixed << miners[a]->getWallet()-> getBalance();
        cout << endl;
    }
    cout << endl;

}
----------------------------------------------------------
Simulator.h
---------------------------------
#ifndef SIMULATOR_H
#define SIMULATOR_H

#include "Transaction.h"
#include "Block.h"
#include "Miner.h"

class Simulator
{
public:
    Simulator(string txfile, string minerNames[], int numMiners);
    ~Simulator();
    void run(int maxIters=300);

private:
    Transaction** pool;
    Block** blockchain;
    Miner** miners;

    int numBlocks;
    int numTx;
    int numMiners;
    const string MINING_TARGET = "00";

    void loadTxPool(string filename);
    void initBlockchain();
    void initMiners(string names[]);
    void removeMinedTxFromPool();
    int getUnminedTxCount();
    bool checkHash(string hash);

};

#endif // SIMULATOR_H
--------------------------------------------------------------------
sha1.cpp
-----------------------------------
#include "sha1.hpp"
#include <sstream>
#include <iomanip>
#include <fstream>


static const size_t BLOCK_INTS = 16; /* number of 32bit integers per SHA1 block */
static const size_t BLOCK_BYTES = BLOCK_INTS * 4;


static void reset(uint32_t digest[], std::string &buffer, uint64_t &transforms)
{
    /* SHA1 initialization constants */
    digest[0] = 0x67452301;
    digest[1] = 0xefcdab89;
    digest[2] = 0x98badcfe;
    digest[3] = 0x10325476;
    digest[4] = 0xc3d2e1f0;

    /* Reset counters */
    buffer = "";
    transforms = 0;
}


static uint32_t rol(const uint32_t value, const size_t bits)
{
    return (value << bits) | (value >> (32 - bits));
}


static uint32_t blk(const uint32_t block[BLOCK_INTS], const size_t i)
{
    return rol(block[(i+13)&15] ^ block[(i+8)&15] ^ block[(i+2)&15] ^ block[i], 1);
}


/*
* (R0+R1), R2, R3, R4 are the different operations used in SHA1
*/

static void R0(const uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i)
{
    z += ((w&(x^y))^y) + block[i] + 0x5a827999 + rol(v, 5);
    w = rol(w, 30);
}


static void R1(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i)
{
    block[i] = blk(block, i);
    z += ((w&(x^y))^y) + block[i] + 0x5a827999 + rol(v, 5);
    w = rol(w, 30);
}


static void R2(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i)
{
    block[i] = blk(block, i);
    z += (w^x^y) + block[i] + 0x6ed9eba1 + rol(v, 5);
    w = rol(w, 30);
}


static void R3(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i)
{
    block[i] = blk(block, i);
    z += (((w|x)&y)|(w&x)) + block[i] + 0x8f1bbcdc + rol(v, 5);
    w = rol(w, 30);
}


static void R4(uint32_t block[BLOCK_INTS], const uint32_t v, uint32_t &w, const uint32_t x, const uint32_t y, uint32_t &z, const size_t i)
{
    block[i] = blk(block, i);
    z += (w^x^y) + block[i] + 0xca62c1d6 + rol(v, 5);
    w = rol(w, 30);
}


/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/

static void transform(uint32_t digest[], uint32_t block[BLOCK_INTS], uint64_t &transforms)
{
    /* Copy digest[] to working vars */
    uint32_t a = digest[0];
    uint32_t b = digest[1];
    uint32_t c = digest[2];
    uint32_t d = digest[3];
    uint32_t e = digest[4];

    /* 4 rounds of 20 operations each. Loop unrolled. */
    R0(block, a, b, c, d, e, 0);
    R0(block, e, a, b, c, d, 1);
    R0(block, d, e, a, b, c, 2);
    R0(block, c, d, e, a, b, 3);
    R0(block, b, c, d, e, a, 4);
    R0(block, a, b, c, d, e, 5);
    R0(block, e, a, b, c, d, 6);
    R0(block, d, e, a, b, c, 7);
    R0(block, c, d, e, a, b, 8);
    R0(block, b, c, d, e, a, 9);
    R0(block, a, b, c, d, e, 10);
    R0(block, e, a, b, c, d, 11);
    R0(block, d, e, a, b, c, 12);
    R0(block, c, d, e, a, b, 13);
    R0(block, b, c, d, e, a, 14);
    R0(block, a, b, c, d, e, 15);
    R1(block, e, a, b, c, d, 0);
    R1(block, d, e, a, b, c, 1);
    R1(block, c, d, e, a, b, 2);
    R1(block, b, c, d, e, a, 3);
    R2(block, a, b, c, d, e, 4);
    R2(block, e, a, b, c, d, 5);
    R2(block, d, e, a, b, c, 6);
    R2(block, c, d, e, a, b, 7);
    R2(block, b, c, d, e, a, 8);
    R2(block, a, b, c, d, e, 9);
    R2(block, e, a, b, c, d, 10);
    R2(block, d, e, a, b, c, 11);
    R2(block, c, d, e, a, b, 12);
    R2(block, b, c, d, e, a, 13);
    R2(block, a, b, c, d, e, 14);
    R2(block, e, a, b, c, d, 15);
    R2(block, d, e, a, b, c, 0);
    R2(block, c, d, e, a, b, 1);
    R2(block, b, c, d, e, a, 2);
    R2(block, a, b, c, d, e, 3);
    R2(block, e, a, b, c, d, 4);
    R2(block, d, e, a, b, c, 5);
    R2(block, c, d, e, a, b, 6);
    R2(block, b, c, d, e, a, 7);
    R3(block, a, b, c, d, e, 8);
    R3(block, e, a, b, c, d, 9);
    R3(block, d, e, a, b, c, 10);
    R3(block, c, d, e, a, b, 11);
    R3(block, b, c, d, e, a, 12);
    R3(block, a, b, c, d, e, 13);
    R3(block, e, a, b, c, d, 14);
    R3(block, d, e, a, b, c, 15);
    R3(block, c, d, e, a, b, 0);
    R3(block, b, c, d, e, a, 1);
    R3(block, a, b, c, d, e, 2);
    R3(block, e, a, b, c, d, 3);
    R3(block, d, e, a, b, c, 4);
    R3(block, c, d, e, a, b, 5);
    R3(block, b, c, d, e, a, 6);
    R3(block, a, b, c, d, e, 7);
    R3(block, e, a, b, c, d, 8);
    R3(block, d, e, a, b, c, 9);
    R3(block, c, d, e, a, b, 10);
    R3(block, b, c, d, e, a, 11);
    R4(block, a, b, c, d, e, 12);
    R4(block, e, a, b, c, d, 13);
    R4(block, d, e, a, b, c, 14);
    R4(block, c, d, e, a, b, 15);
    R4(block, b, c, d, e, a, 0);
    R4(block, a, b, c, d, e, 1);
    R4(block, e, a, b, c, d, 2);
    R4(block, d, e, a, b, c, 3);
    R4(block, c, d, e, a, b, 4);
    R4(block, b, c, d, e, a, 5);
    R4(block, a, b, c, d, e, 6);
    R4(block, e, a, b, c, d, 7);
    R4(block, d, e, a, b, c, 8);
    R4(block, c, d, e, a, b, 9);
    R4(block, b, c, d, e, a, 10);
    R4(block, a, b, c, d, e, 11);
    R4(block, e, a, b, c, d, 12);
    R4(block, d, e, a, b, c, 13);
    R4(block, c, d, e, a, b, 14);
    R4(block, b, c, d, e, a, 15);

    /* Add the working vars back into digest[] */
    digest[0] += a;
    digest[1] += b;
    digest[2] += c;
    digest[3] += d;
    digest[4] += e;

    /* Count the number of transformations */
    transforms++;
}


static void buffer_to_block(const std::string &buffer, uint32_t block[BLOCK_INTS])
{
    /* Convert the std::string (byte buffer) to a uint32_t array (MSB) */
    for (size_t i = 0; i < BLOCK_INTS; i++)
    {
        block[i] = (buffer[4*i+3] & 0xff)
                   | (buffer[4*i+2] & 0xff)<<8
                   | (buffer[4*i+1] & 0xff)<<16
                   | (buffer[4*i+0] & 0xff)<<24;
    }
}


SHA1::SHA1()
{
    reset(digest, buffer, transforms);
}


void SHA1::update(const std::string &s)
{
    std::istringstream is(s);
    update(is);
}


void SHA1::update(std::istream &is)
{
    while (true)
    {
        char sbuf[BLOCK_BYTES];
        is.read(sbuf, BLOCK_BYTES - buffer.size());
        buffer.append(sbuf, is.gcount());
        if (buffer.size() != BLOCK_BYTES)
        {
            return;
        }
        uint32_t block[BLOCK_INTS];
        buffer_to_block(buffer, block);
        transform(digest, block, transforms);
        buffer.clear();
    }
}


/*
* Add padding and return the message digest.
*/

std::string SHA1::final()
{
    /* Total number of hashed bits */
    uint64_t total_bits = (transforms*BLOCK_BYTES + buffer.size()) * 8;

    /* Padding */
    buffer += 0x80;
    size_t orig_size = buffer.size();
    while (buffer.size() < BLOCK_BYTES)
    {
        buffer += (char)0x00;
    }

    uint32_t block[BLOCK_INTS];
    buffer_to_block(buffer, block);

    if (orig_size > BLOCK_BYTES - 8)
    {
        transform(digest, block, transforms);
        for (size_t i = 0; i < BLOCK_INTS - 2; i++)
        {
            block[i] = 0;
        }
    }

    /* Append total_bits, split this uint64_t into two uint32_t */
    block[BLOCK_INTS - 1] = total_bits;
    block[BLOCK_INTS - 2] = (total_bits >> 32);
    transform(digest, block, transforms);

    /* Hex std::string */
    std::ostringstream result;
    for (size_t i = 0; i < sizeof(digest) / sizeof(digest[0]); i++)
    {
        result << std::hex << std::setfill('0') << std::setw(8);
        result << digest[i];
    }

    /* Reset for next run */
    reset(digest, buffer, transforms);

    return result.str();
}


std::string SHA1::from_file(const std::string &filename)
{
    std::ifstream stream(filename.c_str(), std::ios::binary);
    SHA1 checksum;
    checksum.update(stream);
    return checksum.final();
}
-------------------------------------------------------------
sha1.hpp
------------------------------
#ifndef SHA1_HPP
#define SHA1_HPP


#include <cstdint>
#include <iostream>
#include <string>


class SHA1
{
public:
    SHA1();
    void update(const std::string &s);
    void update(std::istream &is);
    std::string final();
    static std::string from_file(const std::string &filename);

private:
    uint32_t digest[5];
    std::string buffer;
    uint64_t transforms;
};


#endif /* SHA1_HPP */
------------------------------------------------------------------------------
Crypto.cpp
---------------------------------
#include <string>
#include <random>

#include "Crypto.h"
#include "sha1.hpp"

using namespace std;

string Crypto::sha1hash(string s)
{
    SHA1 temp;

    temp.update(s);

    return temp.final();
}

string Crypto::sha1hash(int v)
{
    return sha1hash(to_string(v));
}

string Crypto::strtohex(string s, bool u)
{
    string CHARACTERS = "0123456789";
    if (u)
    {
        CHARACTERS += "ABCDEF";
    }
    else
    {
        CHARACTERS += "abcdef";
    }

    int size = s.length();
    string output;
    output.reserve(2*size);

    for (int a=0; a<size; a++)
    {
        const unsigned char c = s[a];
        output.push_back(CHARACTERS[c>>4]);
        output.push_back(CHARACTERS[c&15]);
    }

    return output;
}

string Crypto::random_string(int l)
{
    string output="";

    const char CHARACTERS[] =
            "0123456789"
                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                    "abcdefghijklmnopqrstuvwxyz";

    const int SIZE = (sizeof(CHARACTERS)-1);

    for (int a=0; a<l; a++)
    {
        output += CHARACTERS[rand()%SIZE];
    }

    return output;
}
----------------------------------------------------------
Crypto.h
-----------------------------
#ifndef CRYPTO_H
#define CRYPTO_H

#include <string>

using namespace std;

class Crypto
{
public:
    static string sha1hash(string s);
    static string sha1hash(int v);
    static string strtohex(string s, bool u=true);
    static string random_string(int l);

};

#endif
------------------------------------------------------------------
Block.cpp
-----------------------------------
#include <iostream>
#include <string>
#include <iomanip>

#include "Block.h"
#include "Transaction.h"

using namespace std;

Block::Block(int i, string prevh, string n)
{
    id = i;
    prevBlockHash = prevh;
    minerName = n;

    txCount = 0;
    MAX_TX = 5;
    txList = new Transaction*[MAX_TX];
    blockHash = "";
    confirmed = false;
}

Block::Block(Block& other)
{
    id = other.id;
    txCount = other.txCount;
    MAX_TX = other.MAX_TX;
    blockHash = other.blockHash;
    prevBlockHash = other.prevBlockHash;
    minerName = other.minerName;
    confirmed = other.confirmed;

    txList = new Transaction*[MAX_TX];
    for (int a=0; a<txCount; a++)
        txList[a] = new Transaction(*other.txList[a]);
}

Block::~Block()
{
    for (int a=0; a<txCount; a++)
        delete txList[a];
    delete [] txList;
}

int Block::getId()
{
    return id;
}

bool Block::canAddTransaction()
{
    if (txCount<MAX_TX)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void Block::addTransaction(Transaction *t)
{
    if (canAddTransaction())
    {
        txList[txCount] = new Transaction(*t);
        txCount++;
    }
    else
    {
        cout << "Maximum entries of transactions reached. ";
        cout << "The block cannot accept any more transactions. ";
    }
}

void Block::addTransaction(string f, string t, string s, float a)
{
    if (canAddTransaction())
    {
        txList[txCount] = new Transaction(f, t, s, a);
        txCount++;
    }
    else
    {
        cout << "Maximum entries of transactions reached. ";
        cout << "The block cannot accept any more transactions. ";
    }
}

Transaction *Block::getTransaction(int i)
{
    if(i>=0 && i<txCount)
    {
        return txList[i];
    }
    else
    {
        cout << "Block transaction retrieval unsuccessful: ";
        cout << "index out of bound. ";
        return nullptr;
    }
}

int Block::getNumTransactions()
{
    return txCount;
}

void Block::setBlockHash(string h)
{
    blockHash = h;
}

string Block::getBlockHash()
{
    return blockHash;
}

string Block::getPreviousBlockHash()
{
    return prevBlockHash;
}

string Block::getMinerName()
{
    return minerName;
}

void Block::confirm()
{
    confirmed = true;

    for (int a=0; a<txCount; a++)
    {
        txList[a]->confirm();
    }
}

bool Block::isConfirmed()
{
    return confirmed;
}

void Block::printBlockSummary()
{
    cout << "Block Summary (ID: " << id << ") ";
    cout << "------------------------------------------------------------ ";
    cout << "TxID Amount From To ";
    cout << "------------------------------------------------------------ ";

    for (int a=0; a<txCount; a++)
    {
        cout << txList[a]->getId() << " ";
        cout << setw(6) << setprecision(3) << fixed << txList[a]->getAmount() << " ";
        cout << setw(20) << txList[a]->getSenderAddress() << " ";
        cout << setw(20) << txList[a]->getRecipientAddress() << " ";
    }
}
-----------------------------------------------------------------------
Block.h
--------------------------------------
#ifndef BLOCK_H
#define BLOCK_H

#include <string>

#include "Transaction.h"

using namespace std;

class Block
{
private:
    int id;
    int txCount;
    int MAX_TX;
    Transaction **txList;
    string blockHash;
    string prevBlockHash;
    string minerName;
    bool confirmed;

public:
    Block(int i, string prevh, string n);
    Block(Block& other);
    ~Block();
    int getId();
    bool canAddTransaction();
    void addTransaction(Transaction *t);
    void addTransaction(string f, string t, string s, float a);
    Transaction *getTransaction(int i);
    int getNumTransactions();
    void setBlockHash(string h);
    string getBlockHash();
    string getPreviousBlockHash();
    string getMinerName();
    void confirm();
    bool isConfirmed();
    void printBlockSummary();

};

#endif
------------------------------------------------------------------
transactions.txt
----------------------------------
20
5A747A716E386E705970 7.7964 5470486F38686F434C38 6C4836334138705641615969764B6459786F733830764D756D6C30494F33314536794345576D464D
6B5667493845704F4A63 8.19109 3233597639414E457A6C 4656357636514F3374686B476B4443707969646133673257716841504A49444F7838717349537744
424E3053374253667251 0.768926 546877564A386A6B6573 4A75485342504D34506F506D395473564F73714A6A6E654A753435705262394B6333696951797570
685975744F6368577670 4.6569 6133334174747161516A 43394F4B5643496E306F4E54616F7A3139664B3936574E657A676E473538446B46554F4C41435145
744F344730624F45585A 2.66422 536B556C45544E6C7475 486A43543738767739536D5770556E6D6431745158526B53615046773233434249793273656E3669
33446437666F44626C41 8.57173 46787650686949353741 6258507162756855776E54494D704F416345447835646D414B6E6E337458394770536C7A51545365
556C67304D5651335772 8.28999 327632424E4C63615A59 33496456544570745A534F7A533862444F487042777463644D4F55455A4166616E49454178744E61
794C456B4947394D4739 7.75031 63554439765676556632 4278476B4B3649624934464467684339696C51423436744C65434E756A43636350517A7A72306E52
4F4571366174644A6549 7.88767 4C584C426F5A384C4C39 70386C644E5063634F4E485834346653306A4D4368423751566834335A4872534245486435717436
645779306B503953714D 4.77869 4A473043456F6E4A7871 55746D5A4F444347696158764D366C6330774441304C4D35514F496D4B324E4B3663563732593864
6E574B373867394C3546 0.350733 6637495973585730396B 354B7839665161525A4A6E6F6941774175766C546F586E695A6B50705648786772416F6C6B615148
644A7734646749474551 2.41697 6E61695A553732545442 6777553035306B37494F386A674A33514C724F476D6B644C4B6C6B70626F72344C4A56546B625537
59474A72424664317775 9.28846 377064374D4374306C33 3738716B4A643673386242784A5A5048776273675153316D654D4B68426D34796B4263644B695666
3273686D6D4468674161 4.89988 5962546A767334655979 5A6E324B6B4878347966724A7062457536304A346E75575A796C68694B495A756959627544495870
58466E74697735304F4A 8.4765 4879434876444D497966 4D584A516C4D5939424E65736A796C464E66527346434A6D677955726F5730773157326C6C576A67
30507A61657931766635 2.27839 41694236365859733858 75316B726F6C48416F74643645414F5A4F785442365542306934505A7339456E7A484B5A53764B52
453362344D6F4D527570 5.44597 415138466F55626F7752 57416E367549504C64434F70386D4D36324D4359634A335A4C425648776F684B6C5455355A756A57
72325A477379554A6258 9.50214 5573344B317050796653 547A76495A4C6C4A625173427858574D7459474E4B4F37434F6776324566624A4C53424745585841
47723759476A3979326D 0.375458 665763544D385A317A41 514A3345454E77654447375135797238306E4E577A6B356543315258596A4E4F42654B657A314D74
6A57626A6C4239547546 4.73535 46344438596B4A416C48 515A376E44556757784651504430486E4A7630726E6B306A4C6F7471776F717549763352374B3666

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote