#include <iostream>
#include <ctime>
#include <vector>
#include <string>
#include <sstream>
#include <iomanip>
#include <chrono>
#include <openssl/sha.h>

class Transaction {
public:
    std::string sender;
    std::string receiver;
    double amount;

    Transaction(const std::string& sender, const std::string& receiver, double amount)
        : sender(sender), receiver(receiver), amount(amount) {}
};

class Block {
private:
    int index;
    time_t timestamp;
    std::vector<Transaction> transactions;
    std::string prevHash;
    std::string hash;
    int nonce;

    std::string calculateHash() const {
        std::stringstream ss;
        ss << index << timestamp << transactionString() << prevHash << nonce;
        return sha256(ss.str());
    }

    std::string transactionString() const {
        std::stringstream ss;
        for (const auto& tx : transactions) {
            ss << tx.sender << tx.receiver << tx.amount;
        }
        return ss.str();
    }

    static std::string sha256(const std::string& data) {
        unsigned char digest[SHA256_DIGEST_LENGTH];
        SHA256_CTX ctx;
        SHA256_Init(&ctx);
        SHA256_Update(&ctx, data.c_str(), data.size());
        SHA256_Final(digest, &ctx);

        std::stringstream ss;
        for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
            ss << std::hex << std::setw(2) << std::setfill('0') << (int)digest[i];
        }
        return ss.str();
    }

public:
    Block(int index, const std::vector<Transaction>& transactions, const std::string& prevHash)
        : index(index), timestamp(std::time(nullptr)), transactions(transactions),
          prevHash(prevHash), nonce(0) {
        hash = calculateHash();
    }

    void mineBlock(int difficulty) {
        std::string target(difficulty, '0');
        while (hash.substr(0, difficulty) != target) {
            ++nonce;
            hash = calculateHash();
        }
        std::cout << "Block mined: " << hash << std::endl;
    }

    int getIndex() const { return index; }
    time_t getTimestamp() const { return timestamp; }
    const std::vector<Transaction>& getTransactions() const { return transactions; }
    const std::string& getPrevHash() const { return prevHash; }
    const std::string& getHash() const { return hash; }
};

class Blockchain {
private:
    std::vector<Block> chain;
    int difficulty;

public:
    Blockchain(int difficulty) : difficulty(difficulty) {
        std::vector<Transaction> genesisTransactions;
        genesisTransactions.emplace_back("sender1", "receiver1", 50);
        chain.emplace_back(0, genesisTransactions, "0");
    }

    void addBlock(const std::vector<Transaction>& transactions) {
        chain.emplace_back(chain.size(), transactions, chain.back().getHash());
        chain.back().mineBlock(difficulty);
    }

    bool isValid() const {
        for (size_t i = 1; i < chain.size(); ++i) {
            const Block& currentBlock = chain[i];
            const Block& prevBlock = chain[i - 1];

            if (currentBlock.getHash() != currentBlock.calculateHash()) {
                return false;
            }

            if (currentBlock.getPrevHash() != prevBlock.getHash()) {
                return false;
            }
        }
        return true;
    }
};

int main() {
    Blockchain blockchain(4);

    std::vector<Transaction> transactions1;
    transactions1.emplace_back("sender2", "receiver2", 100);
    blockchain.addBlock(transactions1);

    std::vector<Transaction> transactions2;
    transactions2.emplace_back("sender3", "receiver3", 150);
    blockchain.addBlock(transactions2);

    if (blockchain.isValid()) {
        std::cout << "Blockchain is valid" << std::endl;
    } else {
        std::cout << "Blockchain is not valid" << std::endl;
    }

    return 0;
}
#include <iostream>
#include <ctime>
#include <vector>
#include <string>
#include <sstream>
#include <iomanip>
#include <chrono>
#include <openssl/sha.h>

class Transaction {
public:
    std::string sender;
    std::string receiver;
    double amount;

    Transaction(const std::string& sender, const std::string& receiver, double amount)
        : sender(sender), receiver(receiver), amount(amount) {}
};

class Block {
private:
    int index;
    time_t timestamp;
    std::vector<Transaction> transactions;
    std::string prevHash;
    std::string hash;
    int nonce;

    std::string calculateHash() const {
        std::stringstream ss;
        ss << index << timestamp << transactionString() << prevHash << nonce;
        return sha256(ss.str());
    }

    std::string transactionString() const {
        std::stringstream ss;
        for (const auto& tx : transactions) {
            ss << tx.sender << tx.receiver << tx.amount;
        }
        return ss.str();
    }

    static std::string sha256(const std::string& data) {
        unsigned char digest[SHA256_DIGEST_LENGTH];
        SHA256_CTX ctx;
        SHA256_Init(&ctx);
        SHA256_Update(&ctx, data.c_str(), data.size());
        SHA256_Final(digest, &ctx);

        std::stringstream ss;
        for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
            ss << std::hex << std::setw(2) << std::setfill('0') << (int)digest[i];
        }
        return ss.str();
    }

public:
    Block(int index, const std::vector<Transaction>& transactions, const std::string& prevHash)
        : index(index), timestamp(std::time(nullptr)), transactions(transactions),
          prevHash(prevHash), nonce(0) {
        hash = calculateHash();
    }

    void mineBlock(int difficulty) {
        std::string target(difficulty, '0');
        while (hash.substr(0, difficulty) != target) {
            ++nonce;
            hash = calculateHash();
        }
        std::cout << "Block mined: " << hash << std::endl;
    }

    int getIndex() const { return index; }
    time_t getTimestamp() const { return timestamp; }
    const std::vector<Transaction>& getTransactions() const { return transactions; }
    const std::string& getPrevHash() const { return prevHash; }
    const std::string& getHash() const { return hash; }
};

class Blockchain {
private:
    std::vector<Block> chain;
    int difficulty;

public:
    Blockchain(int difficulty) : difficulty(difficulty) {
        std::vector<Transaction> genesisTransactions;
        genesisTransactions.emplace_back("sender1", "receiver1", 50);
        chain.emplace_back(0, genesisTransactions, "0");
    }

    void addBlock(const std::vector<Transaction>& transactions) {
        chain.emplace_back(chain.size(), transactions, chain.back().getHash());
        chain.back().mineBlock(difficulty);
    }

    bool isValid() const {
        for (size_t i = 1; i < chain.size(); ++i) {
            const Block& currentBlock = chain[i];
            const Block& prevBlock = chain[i - 1];

            if (currentBlock.getHash() != currentBlock.calculateHash()) {
                return false;
            }

            if (currentBlock.getPrevHash() != prevBlock.getHash()) {
                return false;
            }
        }
        return true;
    }
};

int main() {
    Blockchain blockchain(4);

    std::vector<Transaction> transactions1;
    transactions1.emplace_back("sender2", "receiver2", 100);
    blockchain.addBlock(transactions1);

    std::vector<Transaction> transactions2;
    transactions2.emplace_back("sender3", "receiver3", 150);
    blockchain.addBlock(transactions2);

    if (blockchain.isValid()) {
        std::cout << "Blockchain is valid" << std::endl;
    } else {
        std::cout << "Blockchain is not valid" << std::endl;
    }

    return 0;
}